由于JavaScript中并没定义类的方法,(但其依旧将class作为保留关键字),所以我JavaScript面向对象的这部分的印象十分模糊,甚至说几乎是没有。刚开始学JS的时候,只是一味地打代码,并没有十分系统地去规范自己代码,也没有用面向对象的思想去开发。因此,接下来的时间希望自己能好好恶补OOP这一方面的知识。
既然没有JS中没有类的定义方法,那么国外的大牛表示可以自己写一个“类”创建的基“类”,以方便开发者们在开发中强化OOP的思想。这个方法,自己用了一个晚上才勉强看出它的设计思路,毕竟要跟大牛的思路走没那么容易啊,并且书中的代码注释十分详细啊,真是对我这种半吊水的眷顾啊。
简化其他“类”创建的基“类”
// 定义一个名为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.apply(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("warn: Number of floors locked: " + this.floors);
}
});
// 创建新“类”的对象实例
var myAccommodation = new Accommodation();
console.log("myAccommodation instanceof Accommodation: " + (myAccommodation instanceof Accommodation));// true
console.log("myAccommodation instanceof House: " + (myAccommodation instanceof House));// false
var myHouse = new House();
console.log("myHouse.isLocked: " + myHouse.isLocked);// false(由父“类”的initialize方法所设置,该方法被House所继承)
myHouse.lock();// 警告消息: "Number of floors locked : 2"
console.log("myHouse.isLocked: " + myHouse.isLocked);// true
console.log("myHouse instanceof House:" +( myHouse instanceof House));// true
console.log("myHouse instanceof Accommodation: " + (myHouse instanceof Accommodation));// true