以下面这段代码为例,分析ES5原型链中的一些问题
var A = function(name) {
this.name=name
};
A.prototype.n = 1;
var b = new A("tom");
A.prototype = {
n: 2,
m: 3
}//把A的原型对象用一个object覆盖(即function Object()的实例对象)
// b.__proto__ = A.prototype//修改b的原型
// A.prototype.constructor=A
console.log(b.__proto__.constructor==A); //true
console.log(A.prototype); //{n:2,m:3}
console.log(b.n); //1
console.log(b.m); //undefined
console.log(b.__proto__) //A{n:1,constructor:f} 此时f是A,但A的prototype已经改变
console.log(b.__proto__.__proto__.__proto__); //null
//[[Prototype]]和__proto__不一样
//JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过 __proto__ 来访问
//其实[[prototype]]和__proto__意义相同,均表示对象的内部属性,其值指向对象原型。前者在一些书籍、规范中表示一个对象的原型属性,后者则是在浏览器实现中指向对象原型。
console.log(b); // A {name: 'tom'}
var c = new A("jack");
// console.log(b.n);//1
console.log(c.__proto__.constructor==Object) //true
console.log(c.n);//2
console.log(c.m);//3
console.log(c.__proto__)
console.log(c.__proto__.__proto__.__proto__); //null
console.log(c); //A {name: 'jack'}
A.prototype.constructor=A
console.log(c.__proto__.constructor==A) //true
A.prototype = { n: 2, m: 3}将A的原型对象用一个普通函数替代,以至于其中的constructor属性丢失,即构造器丢失- 由于
b是在重置原型对象之前实例化的,所以b中的构造器并没有丢失,并且b的原型对象还是被覆盖之前的原型对象{n:1,constructor:f} - 而c是在重置原型对象之后实例化的,所以
c中的原型函数为一个普通对象{n:2,m:3}(相当于由function Object()实例化之后的对象),该原型函数没有构造器constructor(即构造器丢失),所以会顺着原型链向上查找constructor,找到Object.prototype的constructor,该构造器指向Object b.__proto__.__proto__.__proto__=null
查找路径为:A.prototype->Object.prototype->nullc.__proto__.__proto__.__proto__=null
查找路径为:new Object(普通对象)->Object.prototype->nullA.prototype.constructor=A将重置后的A的原型对象重新指回A本身,所以c.__proto__.constructor==A为true- 若是
b.__proto__ = A.prototype,则相当于b和c有一样的原型对象了
prototype、__proto__和 [[Prototype]]
__proto__是每个对象都具有的属性,prototype是函数独有的属性- JS中一个构造函数默认带一个
prototype属性 prototype指向构造函数的原型对象- 实例中的
__proto__属性,也指向构造函数的原型对象(实例化之前的原型对象) b.__proto__=A.prototype(实例化之前的,若是实例化b之后,又重置了A的prototype,则该等式不成立)- JavaScript中任意对象都有一个内置属性
[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问。其实[[prototype]]和__proto__意义相同,均表示对象的内部属性,其值指向对象原型。前者在一些书籍、规范中表示一个对象的原型属性,后者则是在浏览器实现中指向对象原型。但在chrome中打印出实例对象,会发现不管实例还是构造函数都有[[prototype]]属性,可见[[prototype]]并不是等同于__proto__。
版权声明:本文为qq_44870156原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。