JS中的 prototype和__proto__区别​

1、prototype

每个函数都有一个prototype属性,该属性是一个指针,指向一个对象(构造函数的原型对象) ,这个对象包含所有实例共享的属性和方法。

原型对象都有一个constructor属性,这个属性指向所关联的构造函数。使用这个对象的好处就是可以让所有实例对象共享它所拥有的属性和方法。

这个属性只用js中的类(或者说能够作为构造函数的对象)才会有。

2、 __proto__

每个实例对象都有一个proto属性,用于指向构造函数的原型对象(protitype)。

proto属性是在调用构造函数创建实例对象时产生的。

该属性存在于实例和构造函数的原型对象之间,而不是存在于实例与构造函数之间。

function Person(name, age, job){    
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        console.log(this.name);
    }; // 与声明函数在逻辑上是等价的
}
var person1=new Person("Nicholas",29,"Software Engineer");
console.log(person1);
console.log(Person);
console.log(person1.prototype);//undefined
console.log(person1.__proto__);
console.log(Person.prototype);
console.log(person1.__proto__===Person.prototype);//true

输出结果如下:

总结:

1、调用构造函数创建的实例对象的prototype属性为"undefined",构造函数的prototype是一个对象。
2、proto属性是在调用构造函数创建实例对象时产生的。
3、调用构造函数创建的实例对象的proto属性指向构造函数的prototype,本质上就是继承构造函数的原型属性。
4、在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。

 

原型链

每一个实例对象都有一个__proto__属性,指向的构造函数的原型对象prototype,构造函数的原型对象prototype也是一个对象,也有__proto__属性,这样一层一层往上找直到找到Objectprototype,他的__proto__值为null,这就是原型链。

基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。最直观的表现就是让原型对象指向另一个类型的实例。

当访问实例对象的某个属性时,会先在这个对象本身的属性上查找,如果没有找到,则会通过__proto__属性去原型上找,如果还没有找到,则会在构造函数的原型的__proto__中去找,这样一层层向上查找就会形成一个作用域链,称为原型链。

function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true

SubType.prototype = new SuperType()这句代码使得原来存在于 SuperType 的实例中的所有属性和方法,现在也存在于 SubType.prototype 中。使得instance的constructor指向了SuperType。

console.log(instance.constructor===SuperType);//true

总结: 访问一个实例属性时,首先会在实例中搜索该属性。如果没有找到该属性,则会继续搜索实例的原型。在通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链末端才会停下来。

就拿上面的例子来说,调用 instance.getSuperValue()会经历4个搜索步骤:

  1. 搜索instance实例;
  2. 搜索 SubType.prototype;
  3. 搜索SuperType的实例;
  4. 搜索 SuperType.prototype,最后一步才会找到该方法。

posted on 2024-03-15 10:07  itjeff  阅读(22)  评论(0编辑  收藏  举报

导航