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){
   //...  
}

 

posted @ 2017-08-14 17:31  小小滴白  阅读(175)  评论(0编辑  收藏  举报