写读书笔记的好处在于加深记忆,前一篇总结了编程中创建的对象的几种方式,以及常用的方式,这一篇总结实现继承的方式:
1、对象冒充:
function ClassA(sColor) {
this.color = sColor; this.sayColor = function () { alert(this.color); };
}
function ClassB(sColor, sName) {
this.newMethod = ClassA; this.newMethod(sColor); delete this.newMethod; this.name = sName; this.sayName = function () { alert(this.name); };
}
var objA = new ClassA(“blue”);
var objB = new ClassB(“red”, “John”);
objA.sayColor(); //输出 “blue”
objB.sayColor(); //输出 “red”
objB.sayName(); //输出 “John”
对象冒充可以实现多重继承:
function ClassZ() {
this.newMethod = ClassX; this.newMethod(); delete this.newMethod; this.newMethod = ClassY; this.newMethod(); delete this.newMethod;
}
ECMAScript 的第三版为 Function 对象加入了两个方法,即 call() 和 apply()
2、使用call()方法(与经典的对象冒充方法最相似的方法)
function sayColor(sPrefix,sSuffix) {
alert(sPrefix + **this.color** + sSuffix);
};
var obj = new Object();
obj.color = “blue”;
sayColor.call(obj, “The color is “, “a very nice color indeed.“);
里面的this.color的this就是obj
function ClassB(sColor, sName) {
//this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.call(this, sColor); //执行对象ClassA里面的this.color和this.sayColor语句,而且this代表传入的ClassB,这样就为ClassB添加了两个成员 this.name = sName; this.sayName = function () { alert(this.name); };
}
3、使用apply()方法
apply方法和call方法很类似,
apply方法的使用如下:
function sayColor(sPrefix,sSuffix) {
alert(sPrefix + this.color + sSuffix);
};
var obj = new Object();
obj.color = “blue”;
sayColor.apply(obj, new Array(“The color is “, “a very nice color indeed.“));
创建ClassB的时候可以使用:
(1)
function ClassB(sColor, sName) {
//this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.apply(this, new Array(sColor)); this.name = sName; this.sayName = function () { alert(this.name); };
}
(2)
function ClassB(sColor, sName) {
//this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.apply(this, arguments); this.name = sName; this.sayName = function () { alert(this.name); };
}
可以看到只是出入对象的参数不同而已的,使用的数组或者arguments
4、使用原型链
(1)
function ClassA() {
}
ClassA.prototype.color = “blue”;
ClassA.prototype.sayColor = function () {
alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();
(2)
function ClassB() {
}
ClassB.prototype = new ClassA();
//如果上面的这句代码(ClassB.prototype = new ClassA(); ),在下面的两句代码之后的话,那么添加的name,sayName成员都会丢失
ClassB.prototype.name = ““;
ClassB.prototype.sayName = function () {
alert(this.name);
};
所以在使用这种方式的时候要注意顺序
使用原型链的时候还可以使用instanceof:
var objB = new ClassB();
alert(objB instanceof ClassA); //输出 “true”
alert(objB instanceof ClassB); //输出 “true”
但是使用原型链的弊端是不支持多重继承,原型链会用另一类型的对象重写类的 prototype 属性。
5、混合方式
如果用对象冒充的话就必须使用构造函数方法,所以不是最好的选择,但是使用原型链的话无法使用带参数的构造函数
,比如使用原型链里面的(2)代码,ClassA如果是构造函数,那么创建对象的时候就要先执行
ClassB.prototype = new ClassA(XXX);
再执行:
ClassB.prototype.name = ““;
ClassB.prototype.sayName = function () {
alert(this.name);
};
这样是不现实的,因为你是先把ClassB的原型方法定义好了的,使用的时候要直接创建实例
,这样就不能参数传入ClassA,所以最后采用了混合方式(如下)
function ClassA(sColor) {
this.color = sColor;
}
ClassA.prototype.sayColor = function () {
alert(this.color);
};
function ClassB(sColor, sName) {
ClassA.call(this, sColor); this.name = sName;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function () {
alert(this.name);
};
使用这种方式的时候,可以通过创建ClassB时候传入的参数再传入到ClassA里面使用。
学习小结:
所以最常用的实现继承的方式是混合方式,有原型链也有冒充方式。