prototype和__proto__关系图
概念
prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。
__proto__
是一个对象拥有的内置属性,是JS内部使用寻找原型链的属性。跟浏览器环境有关,IE不可以访问
var Person = function(){};
var p = new Person();
上面创造一个对象,经历三步骤
(1) var p={}; 也就是说,初始化一个对象p
(2) p.__proto__= Person.prototype;
(3) Person.call(p)
p.__proto__ === Person.prototype //true
记住
prototype是构造函数独有的属性;
对象的__prototype__
属性通常与其构造函数的prototype属性相互对应;
所有构造函数的的prototype方法的Object.prototype(除了Object.prototype自身)
ES6 Class的prototype属性和__proto__属性
Class作为构造函数的语法糖,同时有prototype属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype属性的__proto__
属性,表示方法的继承,总是指向父类的prototype属性。
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
子类B的__proto__
属性指向父类A,子类B的prototype属性的__proto__
属性指向父类A的prototype属性。
这样的结果是因为,类的继承是按照下面的模式实现的。
class A {
}
class B {
}
// B的实例继承A的实例
Object.setPrototypeOf(B.prototype, A.prototype);
// B继承A的静态属性
Object.setPrototypeOf(B, A);
《对象的扩展》一章给出过Object.setPrototypeOf方法的实现。
Object.setPrototypeOf = function (obj, proto) {
obj.__proto__ = proto;
return obj;
}
Object.setPrototypeOf(B.prototype, A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;
Object.setPrototypeOf(B, A);
// 等同于
B.__proto__ = A;
这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(__proto__属性)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。
Object.create(A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;