解开AJAX技术生命中的达芬奇密码

来源:CSDNBLOG 作者: 2007-12-03 出处:pcdog.com

ajax  java  javascript  解决方案  漏洞  
上一页 1 2 3 4 5 下一页 
  Douglas Crockford 的Solution:

  现在回溯到上面的示例,在这个示例中唯一的问题就是父类引用是直接的、硬性编写的。它可以适用于小型的类继承环境,但对于具有较深层次的大型继承来讲,这些直接引用非常难于维护。

  那么,有解决方法吗?不幸的是这里没有简单的解决方案

  JavaScript没有提供对通过“隐性引用”方式调用父类方法的支持,这里也没有在其它OO语言中使用的“super”变量的等价物。于是,一些开发者做出了自己的解决方案,但就像我前面提到的那样,每个解决方案都存在某种缺点。

  例如,下面列出的众多著名方法之一:JavaScript大师 [ur=http://en.wikipedia.org/wiki/Douglas_Crockford]Douglas Crockford[/url] 在他的 《Classical Inheritance in JavaScript》 中提出的方法。

  Douglas Crockford的方法在多数情况下可以正常工作:

  一次性支持代码:
//Crockford的方法:给所有的function都增加'inherits' 方法、
//每个类都增加了'uber'方法来调用父类方法
Function.prototype.inherits = function(parent) {
var d = 0, p = (this.prototype = new parent());

this.prototype.uber = function(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;
};
};

  运行示例:

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 项目的客户端代码中使用了大量的父类调用,因此父类调用的可靠性和快速性在项目中是很重要的。
更多内容请看PCdog.com--Ajax的WEB开发  Ajax基础教程  Ajax技术专题
上一页 1 2 3 4 5 下一页 
上一篇:AJAX和Web开发新技术DynamicFaces简介
下一篇:掌控上传进度的AJAX Upload