您的位置:首页 > Web前端 > JavaScript

JavaScript继承实现方法——温故知新

2016-06-02 15:40 543 查看
原型继承示例代码:
<script>
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());
</script>


调用instance.getSuperValue()会经历三个搜索步骤:1)搜索实例;2)搜索SubType.prototype;3)搜索SuperType.prototype,最后一步才会找到该方法。在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链末端才会停下来。

注意:


(1)getSuperValue()方法仍然还在SuperType.prototype中,但property则位于SubType.prototype中。因为property是一个实例属性,而getSuperValue()则是一个原型方法。

(2)给原型添加方法的代码一定要放在替换原型的语句之后。

(3)在通过原型链实现继承是,不能使用对象字面量创建原型方法。因为这样会重写原型链。

示例如下:
//继承了SuperType
SubType.prototype = new SuperType();
 
//使用字面量添加新方法,会导致上一行代码无效
SubType.prototype = {
getSubValue: function(){
return this.subproperty;
}
}


(4)原型链存在的问题:

1)所有实例共享一个超类型构造函数的属性;

2)创建子类型的实例时,不能向超类型的构造函数中传递参数。


So,原型继承很少单独使用!


1、借用构造函数

示例代码:
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instancel1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"


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

(2)传递参数:
function SuperType(name){
this.name = name;
}
function SubType(){
//继承了SuperType,同时还传递了参数
SuperType.call(this, "NBee");
//实例属性
this.age = 20;
}
var intance = new SubType();
alert(intance.name);
alert(intance.age);


存在的问题:

方法都在构造函数中定义,因此函数服用就无从谈起了。

So,借用构造函数的技术也很少单独使用。


2、组合继承

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("Nbee", 20);
instance1.colors.push("black");
alert(instance1.colors);
instance1.sayName();
instance1.sayAge();
 
var instance2 = new SubType("Greg", 21);
alert(instance2.colors);
instance2.sayName();
instance2.sayAge();


组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为JavaScript中最常用的继承模式。


他也有一个缺陷:无论什么情况下,都会调用两次超类型构造函数,一次在创建子类型原型的时候,另一次是在子类型构造函数内部。


所有就有了下面的寄生组合式继承

//寄生组合式继承
function inheritPrototype(subType, superType){
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
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;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
}
 
var p1 = new SubType('p1', 11);
p1.colors.push('black');
p1.sayAge();
p1.sayName();
alert(p1.colors);
var p2 = new SuperType('p2');
p2.sayName();
alert(p2.colors);


寄生组合继承的高效率体现在它只调用了一次SuperType构造函数,并且因此避免了SubType.prototype上面创建不必要的/多余的属性。

大家普遍认为寄生组合式继承是引用类型最理想的继承范式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: