class的本质以及继承链
每个对象都有__proto__属性,指向其构造函数的 prototype 属性。class 构造实例对象,所以其本质依旧是函数,函数同时拥有 prototype 属性和 proto 属性。
class的原型链示例:
class A {}
var a = new A();
/* ES6的class(非继承)的prototype属性是一个对象,该对象拥有两个属性:constructor 和 __proto__,同ES5是一致的 */
A.prototype
/*输出: {constructor: ƒ}
↲constructor: class A >>.constructor指向 本身
↲__proto__: Object(类型) >>. __proto__指向 Object.prototype,说明该对象由Object构造函数构造 */
/* class(继承自父类)的__proto__属性指向其构造函数的prototype属性 */
A.__proto__ === Function.prototype //true
a.__proto__ === A.prototype //true
A.prototype.__proto__ === Object.prototype //true
以上代码可以看出,class就是普通构造函数的语法糖,原型链与普通函数的原型链没有任何差异。
关键字"extends"带来的继承
class可以使用关键字"extends",当时用该关键字继承的子类构造函数和父类构造函数存在着原型链上的链接,该机制是ES6之后class的继承独有的。
示例:
class ASub extends A {}
var asub = new ASub();
asub.__proto__ === ASub.prototype // true 符合原型链
/* 此时,子类的"__proto__"属性直接指向 A */
ASub.__proto__ === A
/* 注意该处的区别,以往的顶层构造函数的"__proto__"属性都是指向 Object.prototype 对象,而该处指向其父类的 prototype 对象 */
ASub.prototype.__proto__ === A.prototype // true
类的继承是按照下面的模式实现的:
class B {}
class BSub {}
// BSub 的实例继承 B 的实例
Object.setPrototypeOf(BSub.prototype, B.prototype);
// BSub 继承 B 的静态属性
Object.setPrototypeOf(BSub, B);
const bsub = new BSub();
BSub.__proto__ === B // true
BSub.prototype.__proto__ === B.prototype //true
Object.setPrototypeOf(obj, prototype)
用来设置一个对象的原型对象("proto"属性),它是 ES6 正式推荐的设置原型对象的方法。