Class的继承3
类的prototype属性和_proto_属性
Class同时具有prototype属性和__proto__属性,因此同时存在两条继承链
a.子类的__proto__属性,表示构造函数的继承,总是指向父类。
b.子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
1 class A{ 2 3 } 4 class B extends A{ 5 6 } 7 B.__proto__ === A //true 8 B.prototype.__proto__ === A.prototype //true
子类B的__proto__属性指向父类A,子类B的prototype属性的__proto__属性指向父类A的protype属性.
类的继承按照下面的模式实现
1 class A{ 2 } 3 class B{ 4 } 5 //B的实例继承A的实例 6 Object.setPrototypeOf(B.prototype,A.prototype); 7 8 //B的实例继承A的静态属性 9 Object.setProtypeOf(B,A); 10 11 const B = new B();
Object.setPrototypeOf方法的实现
Object.setPrototypeOf = function (obj,proto){ obj.__proto__ = proto; return obj; }
1 Object.setPrototypeOf(B.prototype,A.prototype); 2 //等同于 3 B.prototype.__proto__ = A.prototype; 4 5 Object.setPrototype(B,A); 6 //等同于 7 8 B.__proto__ = A;
作为一个对象,子类(B)的原型(__proto__属性)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例
Object.create(A.prototype); //等同于 B.prototype.__proto__ = A.prototype;
extends的继承目标
extends关键字后面可以跟多种类型的值
class B extends A{
}
父类只要有一个prototype属性的函数,就能被B继承。由于函数都有prototype属性(除了Function.prototype函数),因此A可以是任意函数
三种特殊情况:
1.第一种:子类继承object类
class A extends Object { } A.__proto__ ==Object //true A.prototype.__proto__ ===Object.prototype //true
在这种情况下,A其实就是构造函数Object的复刻,A的实例就是Object的实例
2.第二种情况:不存在任何继承
class A{ } A.__proto__ === Function.prototype //true A.prototype.__proto__ === Object.prototype //true
A调用后返回一个空对象(即object实例),所以A.prototype.__proto__指向构造函数(object)的prototype属性
3.第三种情况:子类继承null
class A extends null{ } A.__proto__ ===Function.prototype //true A.prototype.__proto__ === undefined //true
A调用后返回的对象不继承任何方法,所以__proto__指向Function.prototype,即实际上执行了下面的代码
class C extends null{ constructor(){ return Object.create(null); } }
实例的__proto__属性
子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性.即:子类的原型的原型,是父类的原型
var p1 = new Point(2,3); var p2 = new ColorPoint(2,3,'red'); p2.__proto__ === p1.__proto__ //false p2.__proto__.__proto__ === p1.__proto__ //true
colorPoint继承了Point,导致前者原型的原型是后者的原型
因此通过子类实例的__proto__.__proto__属性,可以修改父类实例的行为.
1 p2.__proto__.__proto__.printName = function (){ 2 console.log('Ha'); 3 } 4 p1.printName() //"Ha"
Mixin模式的实现
Mixin模式:将多个类的接口‘混入’(mix in)另一个类.
function mix(...mixins){ class Mix {} for(let mixin of mixins){ copyProperties(Mix, mixin); copyProperties(Mix.prototype,mixin.prototype); } return Mix; } function copyProperties(target,source){ for(let key of Reflect.ownkeys(source)){ if (key !== "constructor" && key !=="prototype" && key !== "name" ){ let desc = Object.getOwnPropertyDescriptor(source,key); object.defineProperty(target,key,desc); } } }
mix函数可以将多个对象合成一个类。使用的时候继承这个类即可
class DistributedEdit extends mix(Loggable,Serializable){ //... }