2017-7-23 深入了解JavaScript继承模式(高程读书笔记)

注:以下内容需要对javascript的原型及原型链有深入理解,备注及图片均出自个人理解,如有不当还望指正.

1.1类式继承
function SuperClass() {};
function SubClass(){};                                             
SubClass.prototype = new SuperClass();  //子类(构造函数)的原型属性指向父类的实例
       //此方法的缺点在于:如果父类上的某以属性是引用数据类型,在修改子类继承自父类上的属性(该属性如果是引用数据类型)的同时会影响到其他子类
1.2构造函数式继承
function SuperClass( id ) {
  this.id = id ;
  this.book = ['Javascript高级程序设计'
];
}
SuperClass.ptototype.showBook = function(){
  console.log(this.book);
};
function SubClass( id ) {
  superClass.call( this , id );
}
//构造函数式继承的精华,通过上下文调用将当前上下文移动到父类构造函数中一日游. -->缺点:该方法并不适用prototype中方法的复刻 , 如果硬要复刻必须将其该方法置于SuperClass构造函数中,但是此举又会违背代码复用原则,使子类拥有单独的重复的showBook方法(增加系统内存的消耗), 由此衍生出组合式继承。

//缺点:无法继承父类原型上的方法
2017-7-23 深入了解JavaScript继承模式(高程读书笔记)_第1张图片
类式继承与函数式继承.png
1.3组合式继承
function SuperClass( id ) {
    this.id = id ;
    this.name = '盛超';
}
SuperClass.prototype.showName = function() {
    console.log( this.name );
}
function SubClass( name ) {
    SuperClass.call( this , name ); //偷父类属性           第二次调用 ->子类实例拥有了自身实例属性,会'覆盖'掉(优先在实例上找)继承自父类实例的实例属性
}
SubClass.prototype = new SuperClass( '420' ); //偷父类方法  第一次调用
SubClass.prototype.showId = function() {} // 定义自身特有方法

//缺点:会过滤掉类式继承中如果父类属性为引用数据类型时修改子类继承自父类的这一引用数据类型的属性,会影响到其他实例的这以缺点,但是父类函数被调用了两次(如果父类函数拥有十分庞大的属性及方法呢,会十分消耗内存,所以并不是最优解决方案。) 
2017-7-23 深入了解JavaScript继承模式(高程读书笔记)_第2张图片
组合式继承.png
1.4原型式继承 -> 类式继承的封装(优化:创建了一个空函数作为中转站) -> subClass.prototype = Object.create( SuperClass.prototype ); 返回的对象的原型指向了SuperClass.prototype->创建一个中转对象其prototype指向父类的原型, 然后使子类的原型指向该中转对象.
function SuperClass( id ) {
  //...
}
function SubClass( id ) {
  //...
}
function extend ( superClass , subClass ){
  var F = function () {}; //中转函数
  subClass.prototype = new F();
  F.prototype = new superClass();
  subClass.constructor = subClass; //修改constructor属性
}
extend( SuperClass , SubClass );  

//解决了父类被调用两次的缺点,但由于时类式继承的上的优化处理,对于父类属性为引用数据类型,在子类上修改该属性依然会影响到其他子类的实例. ->由此引入寄生式继承.
2017-7-23 深入了解JavaScript继承模式(高程读书笔记)_第3张图片
原型式继承.png
小插曲:关于Object.create()方法的实例:->出自Javascript高级程序设计

Object.create()方法的第二个参数与Object.defineproperties()方法(该方法与双向数据绑定原理有关)的第二个参数相同:每个属性都是通过其自定义描述符定义及每个属性都是一个描述对象,并且任何同名属性的传入都会覆盖掉原有属性.

var person = {
    name:'Nicholas',
    friends:['Shelby' , 'Court' , 'Van']
};
var anotherPerson = Obeject.create(person , {
  name:{
     value:'Greg'
  }
});
antherPerson.name //Greg
1.5寄生式继承 ->在原型式继承的基础上进行的进一步封装 ->有点类似JQuery的架构
//原型式继承
function object( o ){
  var F = function () {};
  F.prototype = o;
  return new F();
};

//寄生式继承 ->通过Object函数寄生于传入对象o中,通过AnotherO函数进化增强
function AnotherO ( obj ) {
  var newObj = object( obj );   //通过原型式继承创建一个新的对象,该对象的原型指向obj;
  newObj.sayHello = function() {}; //通过某些方法增强这个对象..
  newObj.run = function () {} ;
  return newObj; //返回这个增强型对象
}

//缺点:由于每次都是在AntherO这个方法中增强对象,所以方法的复用性很低,这点类似于函数式继承:将方法写在构造函数的实例中,会大大增加内存的开销,同时多次调用超类构造器,也会导致效率底下
1.6寄生组合式继承(较为完美的一种继承方式)
//原型式继承(桥接继承)
function object ( o ) {
  var F = function () {};
  F.prototype = o;
  return new F();
}
//寄生组合式继承
    1.0原型继承
function inheritPrototype ( subClass , superClass ) {
  var prototype = object( superClass.prototype ); //创建对象
  prototype.constructor = superClass;  //修改子类constructor为子类构造函数
  subClass.prototype = prototype; //子类原型指向继承父类原型的桥接对象.
}
==>
    1.1原型继承进阶
function inheritPrototype ( subClass , superClass ){
  var F = function () {};
  F.prototype = superClass.protype ;
  subClass.prototype = new F();
  subClass.constructor = subClass; //纠正constructor指向
}

//实例: 寄生组合式继承的高效率体现在它只调用了一次SuperClass的构造函数,同时还避免了在子类实例和原型上分别创建重复的,多余的,不必要的属性,与此同时通过修改constructor的指向,还能保持原型链的不变。于是便可以正常使用instanceof和isPrototypeOf()方法。普遍被认为是寄生组合式继承是引用类型最完美的继承方法. 

    1.0属性继承
function SuperClass ( name ) {
   this.name = name ;
   this.....
}
function SubClass ( name ) {
   SuperClass.call( this , name );  //继承属性 ->唯一的一次调用SuperClass构造函数
}
    2.0原型继承
inheritPrototype( SubClass , SuperClass ); //完成子类继承
SubClass.prototype.sayHello = function () { 
   alert( this.name ); //定义子类多态方法
}
    

你可能感兴趣的:(2017-7-23 深入了解JavaScript继承模式(高程读书笔记))