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; };}; 运行示例:function BaseClass() { }BaseClass.prototype.getName = function() { return "BaseClass(" + this.getId() + ")";}BaseClass.prototype.getId = function() { return 1;}function SubClass() {}SubClass.inherits(BaseClass);SubClass.prototype.getName = function() { //这里看上去非常的清晰,它调用了BaseClass的getName()方法return "SubClass(" + this.getId() + ") extends " + this.uber("getName");}SubClass.prototype.getId = function() { return 2;}function TopClass() {}TopClass.inherits(SubClass);TopClass.prototype.getName = function() { //这里看上去非常的清晰,它调用了SubClass的getName()方法 return "TopClass(" + this.getId() + ") extends " + this.uber("getName");}TopClass.prototype.getId = function() { //Ok, 因此this.getId()应该总是//返回调用SubClass的getId()方法的返回值(2)。 return this.uber("getId");}//输出结果:"TopClass(2) extends SubClass(1) extends BaseClass(1)"//嗯?后面的两次this.getId()调用都没有返回2.//发生了什么? alert(new TopClass().getName()); 上面代码的第一部分包括了Crockford的“inherit”和“uber”方法代码。第二部分看上去和前面的示例很类似,除了我添加了用来演示Crockford方式所存在问题的第三层继承关系。诚然,Crockford这位JavaScript大师的方法是我所找到的最可靠的方法之一,我很敬佩他在JavaScript编程方面做出的贡献。但是,如果你使用三个依次继承的类来考核他的代码,你将从输出中发现这里存在着细微的问题。
从输出结果看,第一次调用的this.getId()返回了TopClass当前的id值“2”,但在调用SubClass和BaseClass的getName()方法时返回了“1”而不是“2”。从代码上看, 在getName()方法中的父类调用行为是正确的,三个类的名字都被正确地显示出来。唯一的问题出现在this.uber("getId")这个父类调用被放入调用堆栈(call stack)时。因为此时当前对象是一个TopClass实例,而每次调用在调用堆栈中的this.getId()都应该返回调用TopClass的getId()方法后的返回值。
而问题是TopClass的this.getId()方法通过this.uber("getId")执行了父类调用,这三次this.getId()调用中的后两次错误地调用了BaseClass的getId()方法,这样便在输出结果中显示了两次“1”。正确的行为应该是调用三次SubClass的getId()方法,在输出结果中显示三次“2”。大家可以通过 FireFox的FireBug插件 进行代码debug进行观察。
这是十分难以描述的现象,我不能保证我能把它解释清楚。但是至少从上面的运行结果中可以看出它是错误的。
另外,Crockford的方法和其它一些方法的劣势在于每个父类调用都需要一个额外的方法调用和额外的某种处理。这是否成为你所面临的问题,取决于你所使用的父类调用深度。在 ThinWire 项目的客户端代码中使用了大量的父类调用,因此父类调用的可靠性和快速性在项目中是很重要的。
我的初级Solution:
面对这样的窘境——Crockford的方法出现