class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
看阮一峰的写的es6的class继承,下面有一句话:
这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(__proto__属性)是父类(A);作为一个构造函数,子类(B)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。
后半句话是不是错了:
作为一个构造函数,子类(B)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。
是不是应该改为:
作为一个构造函数,子类(B)的原型对象(prototype属性)是父类的实例
原文没错。但原文表达得不好。
ES标准中并没有
prototype
是父类prototype
实例的说法。本质上,是基于父类superclass
的prototype
创建了一个新的对象,并且把superclass
的prototype
放到了新创建的对象的内置[[prototype]]
插槽中(详见Runtime Semantics: ClassDefinitionEvaluation和OrdinaryObjectCreate)。并且,由于在访问一个对象时,如果对象上不存在这个属性,但在
[[prototype]]
内部插槽的对象上存在这个属性时,对象继承了访问权限(没有所属权),让这个属性表现为这个对象原型上的属性(详见Ordinary Object Internal Methods and Internal Slots)。通常情况下,如果一个对象B的原型是另一个对象A,人们将它简单地理解为B继承自A,或称A为B的构造类。对于对象B是一个类的情况,将A称为B的父类。所以原文在“理解”上并没有错。我想你对于通过
B.__proto__ === A
得出A是B的父类肯定不会有疑问,那么现在将B
替换为B.prototype
,A
替换为A.prototype
,即(B.prototype).__proto__ === (A.prototype)
,同理可得A.prototype
是B.prototype
的父类。不过,原文的“理解”是从实际看到的出发得出的结论,也就是通过原型的指向得出的父类关系。而实际上,除了构造器本身具备父子关系之外,原型对象只不过通过创建新对象建立了指向关系。这与类是完全独立的过程,所以不存在父子关系。因此,从运行结果的表象上去推论并不是一个特别准确的描述。