t一种没有类的,面向对象的语言,它使用原型继承来代替类继承。
JavaScript一种没有类的,面向对象的语言,它使用原型继承来代替类继承。这个可能对受过传统的面向对象语言(如C++和Java)训练的程序员来说有点迷惑。JavaScript的原型继承比类继承有更强大的表现力,现在就让我们来看看。
Java
JavaScript
强类型
弱类型
静态
动态
基于类
基于原型
类
函数
构造器
函数
方法
函数
但首先,为什么我们如此关心继承呢?主要有两个原因。第一个是类型有利。我们希望语言系统可以自动进行类似类型引用的转换cast。小类型安全可以从一个要求程序显示地转换对象引用的类型系统中获得。这是强类型语言最关键的要点,但是这对像JavaScript这样的弱类型语言是无关的,JavaScript中的类引用无须强制转换。
第二个原因是为了代码的复用。在程序中常常会发现很多对象都会实现同一些方法。类让建立单一的一个定义集中建立对象成为可能。在对象中包含其他对象也包含的对象也是很常见的,但是区别仅仅是一小部分方法的添加或者修改。类继承对这个十分有用,但原型继承甚至更有用。
要展示这一点,我们要介绍一个小小的“甜点”可以主我们像一个常规的类语言一样写代码。我们然后会展示一些在类语言中没有的有用的模式。最后,我们会就会解释这些“甜点”。
类继承
首先,我们建立一个Parenizor类,它有成员 value的get和set方法,还有一个会将value包装在括号内的toString方法。
function Parenizor(value) {
this.setValue(value);
}
Parenizor.method('setValue', function (value) {
this.value = value;
return this;
});
Parenizor.method('getValue', function () {
return this.value;
});
Parenizor.method('toString', function () {
return '(' + this.getValue() + ')';
});
myParenizor = new Parenizor(0);
myString = myParenizor.toString();
function ZParenizor(value) {
this.setValue(value);
}
ZParenizor.inherits(Parenizor);
ZParenizor.method("e;toString"e;, function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-";
});
myZParenizor = new ZParenizor(0);
myString = myZParenizor.toString();
ZParenizor.swiss(NumberValue, 'setValue', 'setRange');
function ZParenizor2(value) {
var self = new Parenizor(value);
self.toString = function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-"
};
return self;
}
myParenizor = new Parenizor(0);
myParenizor.toString = function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-";
};
myString = myParenizor.toString();
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Function.method('inherits', function (parent) {
var d = 0, p = (this.prototype = new parent());
this.method('uber', function uber(name) {
var f, r, t = d, v = parent.prototype;
if (t) {
while (t) {
v = v.constructor.prototype;
t -= 1;
}
f = v[name];
} else {
f = p[name];
if (f == this[name]) {
f = v[name];
}
}
d += 1;
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
d -= 1;
return r;
});
return this;
});
Function.method('swiss', function (parent) {
for (var i = 1; i < arguments.length; i += 1) {
var name = arguments[i];
this.prototype[name] = parent.prototype[name];
}
return this;
});