说明:本文为《JavaScript高级程序设计》第4章学习笔记。
一. 继承机制实例
几何形状只有两种,即椭圆形和多变形。圆是椭圆形的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了继承关系。
形状是椭圆形和多边形的基类。圆形继承了椭圆形,因此圆形是椭圆形的子类,椭圆形是圆形的超类。
二. 继承机制的实现
要用ECMAScript实现继承机制,首先从基类入手。所有开发者定义的类都可以作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。
选定基类后,就可以创建它的子类了。是否使用基类完全由你决定。有时,你可能想创建不能直接使用的基类,它只是用户给予类公共通用的函数。在这种情况下,基类被看作抽象类。
1.继承的方式
JavaScript中的继承机制并不是明确规定的,而是通过模仿实现的。开发者可以自己决定最适用的继承方式。
1)对象冒充
原理:构造函数使用this关键字给所有属性和方法赋值。因为构造函数只是一个函数,所以可使ClassA的构造函数成为ClassB的方法,然后调用它。ClassB就会收到ClassA的构造函数定义的属性方法。
Eg.
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);
}
}
2)call()方法
call()方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作this的对象,其他参数都直接传递给函数本身。
Eg. 可将上例中的ClassB改成如下后,可达到先前同样的效果:
function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
this.sayName = function() {
alert(this.name);
}
}
3)apply()方法
该方法有两个参数,用作this的对象要传递给的参数的数组。
Eg.
function sayColor(sPrefix, sSuffix) {
alert(sPrefix + this.color + sSuffix);
};
var obj = new Object();
obj.color = "red";
sayColor.apply(obj, new Array("The color is ", ", a very nice color indeed."));
可将上述的ClassB修改为如下这样:
function ClassB(sColor, sName) {
ClassA.apply(this, new Array(sColor));
this.name = sName;
this.sayName = function() {
alert(this.name);
};
}
4)原型链
Prototype对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
Eg.
function ClassA() {
}
ClassA.prototype.color = "red";
ClassA.prototype.sayColor = function() {
alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = "";
ClassB.prototype.sayName = function() {
alert(this.name);
};
原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的prototype属性。
5)混合模式
对象冒充的主要问题是必须使用构造函数的方式,这不是最好的选择。不过如果使用原型链,就无需使用构造函数了。如果将这两种方式混合起来,将会达到更好的效果。
Eg.
fuction 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 = function() {
alert(this.name);
};
调用代码如下所示:
var objA = new ClassA("red");
var objB = new ClassB("blue", "AmigoXie");
objA.sayColor();
objB.sayColor();
objB.sayName();
2.一个更实际的例子
下面讲一个Polygon、Triangle和Rectangle的例子。
1)创建基类Polygon
Eg.
function Polygon(iSides) {
this.sides = iSides;
}
Polygon.prototype.getArea = function() {
return 0;
};
2)创建子类
三角形Triangle的内容如下:
function Triangle(iBase, iHeight) {
Polygon.call(this, 3);
this.base = iBase;
this.height = iHeight;
}
Triangle.prototype = new Polygon();
Triangle.prototype.getArea = function() {
return 0.5 * this.base * this.height;
};
Rectangle的ECMAScript代码如下:
function Rectangle(iLength; iWidth) {
Polygon.call(this, 4);
this.length = iLength;
this.width = iWidth;
}
Rectangle.prototype = new Polygon();
Rectangle.prototype = function() {
return this.length * this.width;
};
3)测试代码
var triangle = new Triangle(12, 4);
var rectangle = new Rectangle(22, 10);
alert(triangle.sides);
alert(triangle.getArea());
alert(rectangle.sides);
alert(rectangle.getArea());
4)采用动态原型方法如何?
function Polygon(iSides) {
this.sides = iSides;
if (typeof Polygon._initialized == "undefined") {
Polygon.prototype.getArea = function() {
return 0;
};
Polygon._initialized = true;
}
}
function Triangle(iBase, iHeight) {
Polygon.call(this, 3);
this.base = iBase;
this.height = iHeight;
if (typeof Triangle._initialized == "undefined") {
Triangle.prototype = new Polygon();
Triangle.prototype.getArea = function() {
return 0.5 * this.base * this.height;
};
Triangle. _initialized = true;
}
}
Triangle.prototype = new Polygon();
三. 小结
本章介绍了ECMAScript中用对象冒充和原型链实现的继承概念。学会结合使用这些方式才是建立类之间的继承机制的最好方式。
posted on 2007-09-04 08:59
阿蜜果 阅读(935)
评论(3) 编辑 收藏 所属分类:
Javascript