《JavaScript 高级程序设计》学习总结六(4)

引言:上一章我们提到过:继承采用原型链方式实现,而原型在实现属性共享上有优势也有缺点,所以原型链实现继承也是不可避免碰到这样的问题,第二个情况是:在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上, 应该说是没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。这一章节,我们针对继承实现的问题,我们总结学习几种实现继承的方法。

1、借用构造函数

在子类型构造函数的内部调用超类型构造函数。函数是在特定环境中执行代码的对象, 因此通过使用 apply()和 call()方法也可以在(将来)新创建的对象上执行构造函数,举个例子:

 1 function SuperType(){
 2  this.colors = ["red", "blue", "green"];
 3 }
 4 function SubType(){
 5  //继承了 SuperType
 6  SuperType.call(this);
 7 }
 8 var instance1 = new SubType();
 9 instance1.colors.push("black");
10 alert(instance1.colors); //"red,blue,green,black"
11 var instance2 = new SubType();
12 alert(instance2.colors); //"red,blue,green" 

代码中加下划线的那一行代码“借调”了超类型的构造函数。通过使用 call()方法(或 apply()方法 也可以),我们实际上是在(未来将要)新创建的 SubType 实例的环境下调用了 SuperType 构造函数。 这样一来,就会在新 SubType 对象上执行 SuperType()函数中定义的所有对象初始化代码。结果, SubType 的每个实例就都会具有自己的 colors 属性的副本了。

相对于原型链而言,借用构造函数有一个很大的优势:

1传递参数:即可以在子类型构造函数中向超类型构造函 数传递参数。

function SuperType(name){
 this.name = name;
}
function SubType(){
 //继承了 SuperType,同时还传递了参数
 SuperType.call(this, "Nicholas");

 //实例属性
 this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29 

如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定 义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结 果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

组合继承 组合继承(combination inheritance),

有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方 法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数 复用,又能够保证每个实例都有它自己的属性

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);

 this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
 alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27 

  在这个例子中,SuperType 构造函数定义了两个属性:name 和 colors。SuperType 的原型定义 了一个方法 sayName()。SubType 构造函数在调用 SuperType 构造函数时传入了 name 参数,紧接着 又定义了它自己的属性 age。然后,将 SuperType 的实例赋值给 SubType 的原型,然后又在该新原型 上定义了方法 sayAge()。这样一来,就可以让两个不同的 SubType 实例既分别拥有自己属性——包 括 colors 属性,又可以使用相同的方法了。 组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继 承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象。

原型式继承:

寄生式继承

寄生组合式继承

-----------------------------------------------------------------------本章留坑---------------------------------------------------------

猜你喜欢

转载自www.cnblogs.com/wxhhts/p/9482059.html