浅谈JavaScript中继承的实现

时间:2021-09-06 14:43:33

谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我已就在JavaScript中对象创建的方法做了一些总结,下面就其继承来道说一二:

:原型链继承:

   每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针

(默认的原型,所有默认类型都继承了Object,而这个继承也是用过原型链实现)

function SuperType(){
this.property = true;
} SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
} //继承SuperType
SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function(){
return this.subproperty;
};
var instance = new SubType();
alert(instance.property); alert(instance.getSuperValue());
alert(instance.getSubValue());

原型继承的问题:

   1:原型属性被所有实例所共享   一个改变,其余跟着改变。
2:在创建子类型的实例时,不能向超类型的构造函数中传递参数
总结:实践中很少会单独使用原型链 (这似乎和对象创建时的问题如出一辙) 2:借用构造函数创建:
        function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
// 继承了SubType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //["red", "blue", "green", "black"] var instance2 = new SubType()
alert(instance2.colors); //["red", "blue", "green"]没哟随某个实例
                                    //的更改而更改
//--------------------------------------------------------------------------
// 参数传递:
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

缺点:方法都在构造函数里面定义,因此函数复用就无从谈起(什么意思呢:摸索中)。

组合继承:

//        组合继承:
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);
}; var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);
instance1.sayName();
instance1.sayAge(); var instance2 = new SubType("Greg",27);
alert(instance2.colors);
instance2.sayName();
instance2.sayAge();

自然,这种组合式创建也有其不到之处,即来两次调用了SuperType构造函数,使得实例属性colors和name的重复创建,后一次创建的自然会覆盖前面的。

随引出<寄生组合式继承>

上代码:

//寄生组合式继承:
function inheritPrototype(subType , superType){
var prototype = Object(superType.prototype); //创建对象原型的一
//个副本
//为创建的副本添加constructor属性,使其指向自己的构造函数
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);
};

从代码中,咋们可以看出,值调用了一次SuperType的构造函数,固然就没有什么多余的不必要的属性创建。