深入理解继承知识(下)

JavaScript继承模式详解

640?wx_fmt=png

原型式继承

他的想法是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。



 
function create(o){	
  function F(){}	
  F.prototype = o;	
  return new F();	
}


在 create() 函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例。


ECMAScript 5通过新增 Object.create() 方法规范化了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下, Object.create() 与 create() 方法的原理相同。



 
let person = {	
  name: 'Nicholas',	
  friends: ['Shelby', 'Court', 'Van']	
};	
let anotherPerson = Object.create(person);	
anotherPerson.name = 'Greg';	
anotherPerson.friends.push('Rob');	
let yetAnotherPerson = Object.create(person);	
yetAnotherPerson.name = 'Linda';	
yetAnotherPerson.friends.push('Barbie');	
alert(person.friends); // 'Shelby,Court,Van,Rob,Barbie'

Object.create() 方法的第二个参数与 Object.defineProperties() 方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。



 
let person = {	
  name: 'Nicholas',	
  friends: ['Shelby', 'Court', 'Van']	
};	
let anotherPerson = Object.create(person, {	
  name: {	
    value: 'Greg'	
  }	
});	
alert(anotherPerson.name); //'Greg'

寄生式继承

寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。以下代码示范了寄生式继承模式。



 
function createAnother(original) {	
  let clone = Object.assign({}, original); //通过调用函数创建一个新对象	
  clone.sayHi = function () { //以某种方式来增强这个对象	
    alert('hi');	
  };	
  return clone; //返回这个对象	
}

寄生组合式继承

前面说过,组合继承是JavaScript最常用的继承模式;不过,它也有自己的不足。组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。没错,子类型最终会包含超类型对象的全部实例属性,但我们不得不在调用子类型构造函数时重写这些属性。再来看一看下面组合继承的例子。



 
function SuperType(name) {	
  this.name = name;	
  this.colors = ['red', 'blue', 'green'];	
}	
SuperType.prototype.sayName = function () {	
  alert(this.name);	
};	
function SubType(name, age) {	
  SuperType.call(this, name); //第二次调用SuperType()	
  this.age = age;	
}	
SubType.prototype = new SuperType(); //第一次调用SuperType()	
SubType.prototype.constructor = SubType;	
SubType.prototype.sayAge = function () {	
  alert(this.age);	
};


有两组 name 和 colors 属性:一组在实例上,一组在 SubType 原型中。这就是调用两次 SuperType 构造函数的结果。好在我们已经找到了解决这个问题方法——寄生组合式继承。


所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所示。



 
function SuperType(name) {	
  this.name = name;	
  this.colors = ['red', 'blue', 'green'];	
}	
SuperType.prototype.sayName = function () {	
  console.log(this.name);	
};	
function SubType(name, age) {	
  SuperType.call(this, name);	
  this.age = age;	
}	
SubType.prototype = Object.create(SuperType.prototype, { constructor: { value: SubType } })	
SubType.prototype.sayAge = function () {	
  console.log(this.age);	
};


这个例子的高效率体现在它只调用了一次 SuperType 构造函数,并且因此避免了在 SubType.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf() 。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。


640?wx_fmt=png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值