这里是前面示例的,但是目前这种方式包括了通过“extend”方法实现的十分清晰的类定义模式和正确的父类调用语义。尤其是“extend”方法通过一个中间function封装了类定义中的每个方法,这个中间function在每次方法调用时首先把当前父类引用“contentrdquo; 与正确的父类引用相互交换,然后把这个正确的父类引用传递给apply()进行方法调用,最后再将把当前父类引用“contentrdquo; 与正确的父类引用交换回来。这种方式唯一的问题就是它需要一些中间function,它们会对性能产生不良影响。所以近来我重新审视了设计、完成了去掉了中间function了一种改良的方式。
改良后的Solution:
动态父类调用快速版本:
一次性支持代码
//定义最顶级类function Class() { }Class.prototype.construct = function() {};Class.extend = function(def) { var classDef = function() { if (arguments[0] !== Class) { this.construct.apply(this, arguments); } }; var proto = new this(Class); var superClass = this.prototype; for (var n in def) { var item = def[n]; if (item instanceof Function) item.$ = superClass; proto[n] = item; } classDef.prototype = proto; //赋给这个新的子类同样的静态extend方法 classDef.extend = this.extend; return classDef;}; 运行示例://Hey, 注意一下这个类的定义方式//看上去比其它方式要清楚些var BaseClass = Class.extend({ construct: function() { /* optional constructor method */ }, getName: function() { return "BaseClass(" + this.getId() + ")"; }, getId: function() { return 1; }});var SubClass = BaseClass.extend({ getName: function() { //调用BaseClass的getName()方法 return "SubClass(" + this.getId() + ") extends " + arguments.callee.$.getName.call(this); }, getId: function() { return 2; }});var TopClass = SubClass.extend({ getName: function() { //调用SubClass的getName()方法 return "TopClass(" + this.getId() + ") extends " + arguments.callee.$.getName.call(this); }, getId: function() { // this.getId()总是返回调用父类的getId()方法的返回值(2) return arguments.callee.$.getId.call(this); }});//输出结果:"TopClass(2) extends SubClass(2) extends BaseClass(2)"//工作正常!而且没有任何中间functionalert(new TopClass().getName());
这是最后的设计,它使用了JavaScript中一点鲜为人知的特性:callee。
在任何方法执行过程中,你可以查看那些通过“arguments”数组传入的参数,这是众所周知的,但很少有人知道“arguments”数组包含一个名为“callee”的属性,它作为一个引用指向了当前正在被执行的function,而后通过“contentrdquo;便可以方便的获得当前被执行function所在类的父类。这是非常重要的,因为它是获得此引用的唯