摘自《精通 JavaScript 开发》:
小二儿,上代码~
// 定义一个名为 Class 的对象,该对象有一个 create() 方法用于创建新的“类”。我们用闭包来维护内部函数,
// 避免公开暴露这些函数
var Class = (function() {
// 调用 create() 方法时,它将根据一个对象直接量来定义并返回一个新的“类”,该对象直接量为这个
// “类”的原型提供了各种公有的属性和方法。一个名为 initialize() 的方法将被作为构造函数来执行。如果
// 代表父“类”的可选参数 parentPrototype 被传入,则新创建的“类”将成为该父“类”的子类
function create(classDefinition, parentPrototype) {
// 定义新“类”的构造函数,如果 classDefinition 对象直接量包含 initialize() 方法,则在构造函数
// 中使用该方法
var _NewClass = function() {
if (this.initialize && typeof this.initialize === 'function') {
this.initialize.apply(this, arguments);
}
},
_name;
// (在继承其他“类”时) 如果传入了一个 parentPrototype 对象,
// 则子类将继承 parentPrototype 的所有属性和方法
if (parentPrototype) {
_NewClass.prototype = new parentPrototype.constructor(); // 创建子类
for (_name in parentPrototype) {
if (parentPrototype.hasOwnProperty(_name)) {
_NewClass.prototype[_name] = parentPrototype[_name];
}
}
};
// 通过定义一个函数来创建闭包,然后在闭包中返回另一个函数来替代传入的函数
// 将传入的函数包装起来,并为当前对象提供一个 __parent() 方法,
// 以支持父“类”中同名方法的访问,这样就实现了对多太的支持
function polymorph(thisFunction, parentFunction) {
return function () {
var output;
this.__parent = parentFunction;
output = thisFunction.apple(this, arguments);
delete this.__parent;
return output;
};
}
// 将作为参数传入的“类”定义应用到新创建的“类”上,
// 覆盖所有 parentPrototype 中已存在的属性和方法
for (_name in classDefinition) {
if (classDefinition.hasOwnProperty(_name)) {
// 如果正在利用多态,即创建和父“类”方法同名的新方法,
// 我们希望提供一种在子“类”同名方法的简单方式
if (parentPrototype && parentPrototype[_name] && typeof classDefinition[_name] === 'function') {
_NewClass.prototype[_name] = polymorph(classDefinition[_name], parentPrototype[_name]);
} else {
// 如果不需要多态,则直接将 classDefinition 对象直接量中的项映射到新“类”的类型即可
_NewClass.prototype[_name] = classDefinition[_name];
}
}
}
// 确保构造函数属性设置正确,不管是否继承
// (以防 classDefinition 对象直接量包含名为 constructor 的属性或方法)
_NewClass.prototype.constructor = _NewClass;
// 为新创建的“类”自身定义一个 extend() 方法,指向私有的 extend() 函数,这个函数定义在下面,
// 我们通过此方法可以将当前“类”作为父“类”来创建一个新的子类
_NewClass.extend = extend;
return _NewClass;
}
// extend() 与 create() 方法相同,不过隐含了一个额外的参数,即用来进行继承的父“类”的原型
function extend(classDefinition) {
return create(classDefinition, this.prototype);
}
// 用相同的名字将私有的 create() 方法暴露
return {
create: create
};
}());
实现一下:
// 通过 Class.create 定义一个“类”,传入一个对象直接量,该对象包含那些将为新“类”所拥有的公有属性
// 和方法。initialize 方法将成为新类的构造函数
var Accommodation = Class.create({
isLocked: true,
isAlarmed: true,
lock: function() {
this.isLocked = true;
},
unlock: function() {
this.isLocked = false;
},
initialize: function() {
this.unlock();
}
});
// Class.create 在创建的所有“类”上添加了一个 extend 方法,我们使用该方法来创建 Accommodation 的子类,
// 以实现简单的继承。父“类”的所有公有方法和属性对子类都可用,如果同名则子类覆盖父类
var House = Accommodation.extend({
floors: 2,
lock: function() {
// 虽然正在用多态来替换父“类”中的同名方法,仍可通过 this.parent() 访问被替换的父“类”方法
this._parent();
console.log("Number of floors locked:" + this.floors);
}
});
// 创建新“类”的对象实例
var myAccommodation = new Accommodation();
var myHouse = new House();