一些原型的理解(2)

关于原型的一些理解

  1. 函数的prototype属性

    • 每个函数都有一个prototype属性,即显式原型(属性), 它默认指向一个Object空对象(即称为: 原型对象)

    • 原型对象中有一个属性constructor, 它指向函数对象

    • 原型对象还有一个__proto__属性,这是实例对象都有的属性,可称为隐式原型(属性),对象的隐式原型的值为其对应构造函数的显式原型的值

      function fn(name) {
      	this.name = name
      }
      console.log(fn.prototype)
      --------------------------------------------
      {
          constructor: ƒ fn(name)
          __proto__: Object   
      }
      
  2. 给原型对象添加属性(一般都是方法)

    • 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
  3. 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象

    对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值

  4. 所有函数都是Function的实例(包含Function自己),所以所有函数既可以是构造函数也可以是实例对象,也就是说所有函数中中既有__proto__也有prototype

    console.log(fn.__proto__ === Function.prototype)  //true
    console.log(Function.__proto__ === Function.prototype)  //true
    

原型图

constructor的作用

  1. 为什么Father.constructor !== Father.prototype.constructor?

    function Person(area){
      this.type = 'person';
      this.area = area;
    }
    Person.prototype.sayArea = function(){
      console.log(this.area);
    }
    var Father = function(age){
      this.age = age;
    } 
    Father.prototype = new Person('Beijin');
    console.log(Person.prototype.constructor) //function person()
    console.log(Father.prototype.constructor); //function person()
    Father.prototype.constructor = Father;     //修正
    console.log(Father.prototype.constructor); //function father()
    var one = new Father(25);
    
    ----------------------------------------
    Father.prototype.constructor = Father,这里修正了的Father的constructor。
    我们知道prototype下的constructor属性返回对创建此对象的函数的引用。
    
    • __proto__是所有对象(包括函数)都有的,它才叫做对象的原型,原型链就是靠它形成的。因此查找原型链上的属性和方法都是从__proto__查找的。
    • prototype只有函数(准确地说是构造函数)才有的。它跟原型链没有关系。它的作用是:构造函数new对象的时候,告诉构造函数新创建的对象的原型是谁。
    • 而Father.constructor,是从Father的原型链查找属性,也就是__proto__,因为Father继承的是Function(){},而Function(){}的constructor就是它自己
      所以Father.constructor = function Function();
    • 不修正的话,Father.prototype.constructor = function Person()
  2. 为什么需要修正Father.prototype.constructor = Father?

    var man;
    (function(){
      function Father (name) {
        this.name = name;
      }
    
      Father.prototype.sayName= function () {
        console.log(this.name);
      }
      man = new Father('aoyo');
    })()
    man.sayName();//aoyo
    
    console.log(Father); //Father is not defined
    

    上述代码中Father在闭包中,所有我们不能直接访问,当我们想对Father类增加方法时可以通过

    man.constructor.prototype.sayAge = function(age){
        console.log(age);
    }
    man.sayAge('20'); //20
    

    并且如果像上面一样Father.prototype = new Person('Beijin')同时不进行修正,我们的方法将会添加到Person类,而不是Father类。

一些题目

(1)

function F() {
  this.a = 1;
}
var obj = new F();
console.log(obj.prototype);//打印undefined   对象只有 __proto__属性没有prototype属性,函数才有

(2)

Object.prototype.a = 1;
var obj = {
    b: 2
};
for(var i in obj) {
    console.log(i); //能迭代出原型链里面的属性,所以会打印出 b和a
}

(3)

Object.prototype.a = 1; 
var obj = {
    b: undefined
};
 
console.log(obj.a);//1
console.log('b' in obj);//true  //能找到处于原型链里面的bar属性
 
console.log(obj.hasOwnProperty('a'));//false 不是自身的属性
console.log(obj.hasOwnProperty('b'));//true  是自身的属性

(4)

function A(){
}
function B(a){
  this.a = a;
}
function C(a){
  if(a){
		this.a = a;
  }
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
 //实例对象都能访问构造函数的原型对象,可以明确的是以上3个都是能拿到a的
 
console.log(new A().a);//1   拿到的是原型上的a=1
console.log(new B().a);//undefined  this.a = a;将new B()这个实例对象的a属性这是为undefined,所以拿到的是undefined
console.log(new C(2).a);//2   将new C(2)这个实例对象的a属性这是为2,所以拿到的是2

(5)

function A () {
}
A.prototype.n = 1;
 
var b = new A();//b实例对象已经建立原型连接
 
//原型对象指向被改变,不会切断b实例对象的
A.prototype = {
    n: 2,
    m: 3
}
var c = new A();//c实例对象将根据新的原型建立连接
 
console.log(b.n, b.m); //1 undefined  这里拿到是改变prototype之前的
console.log(c.n, c.m); //2 3		这里拿到是改变prototype之后的

(6)

var F = function(){};
Object.prototype.a = function(){
    console.log('a')
}
Function.prototype.b = function(){
    console.log('b')
}
var f = new F();
 
F.a();  //打印a  对象都能访问Object.prototype中的属性和方法
F.b();  //打印b  F是函数,原型链  F => F.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
 
f.a();  //打印a  对象都能访问Object.prototype中的属性和方法
f.b();  //报错f.b is not a function   因f是F实例对象,原型链 f=>f.__proto__=>F.prototype=>F.prototype.__proto__ => Object.prototype

https://blog.csdn.net/weixin_42614080/article/details/93413476

posted @ 2021-03-02 20:42  Hhhighway  阅读(71)  评论(0编辑  收藏  举报