所以我在一些 JavaScript 代码中有一个错误,这让我有些发疯。我一直在尝试模仿 JavaScript 中的经典继承(我知道,我知道,我在这里读到的一半帖子都说不要将 JavaScript 扭曲成这样的框架,但我的应用程序需要有一个映射到我的服务器端 php 代码的继承结构)。大多数情况下,看起来一切正常。这是我用来扩展类的函数:
Function.prototype.inheritsFrom = function(parentClass) {
//:: Ordinary Classes
if (parentClass.constructor == Function) {
this.prototype = new parentClass();
this.prototype.constructor = this;
this.prototype.parent = parentClass.prototype;
//:: Abstract Classes
} else {
this.prototype = parentClass;
this.prototype.constructor = this;
this.prototype.parent = parentClass;
}
return this;
}
不是我自己的创作,我在网上找到的,但效果很好。我唯一需要添加的是一个“超级”函数来搜索原型链的父方法;上述代码中的父结构并非在所有情况下都有效。
无论如何,由于我一直在解决我的代码中的一些错误,我发现我的基“类”中的一种方法是访问/修改从其所有子类创建的所有实例的相同变量。换句话说,每当一个实例修改这个应该是其对象上下文本地的变量时,它实际上修改了一些在所有实例之间共享的变量。这是基类:
function DataManipulatorControl() {
//|| Private Members ||//
var that = this;
//|| Properties ||//
//|| Root ID
this.rootID = function(value) {
if (value !== undefined) {
if (_root_id !== null) {
alert('@ ' + _root_id);
$('#' + _root_id).prop('js_object', null);
}
_root_id = value;
$('#' + _root_id).prop('js_object', this);
}
return _root_id;
}
var _root_id = null;
// other properties/methods
}
//|| Class: DataManipulatorContainerControl
function DataManipulatorContainerControl() {
//|| Private Members ||//
var that = this;
// subclass properties/methods
}
DataManipulatorContainerControl.inheritsFrom(DataManipulatorControl);
正如我所提到的,当我创建这些原型的新实例时,我发现更改一个实例的 rootID 会改变所有实例。我的第一个想法是我在某处忘记了“var”,而我的函数正在访问全局上下文。不过,情况似乎并非如此,所以我的下一个想法是它使用了原型本地的变量。不过,这对我来说也没有多大意义,因为原型构造函数调用的本地变量不应该在它之外访问,除非由已经在范围内的方法访问。当然,rootID() 函数确实在范围内,但我的印象是它将使用调用对象的对象上下文而不是原型来运行。
所以,我很困惑。任何可以在这个问题上阐明的观点都会唤起我们的感激之情。
编辑: PRB 提供的文章描述了一个干净地解决这个问题的解决方案 - 主要是。文章指出,您还需要从子类构造函数中调用父类的构造函数以正确初始化所有内容。结果,所有的方法都是新创建的,它们自己的父类局部变量版本都在闭包中。
这种方法似乎确实存在一个缺点(除了在每个实例中复制函数的效率问题)。如果一个人试图从原型链中调用“覆盖”的函数来尝试超级功能,那么这个问题将再次出现。和以前一样,原型是单个对象的实例,尝试调用它们的函数版本将导致它们尝试访问其实例的局部变量。
仍然是我见过的最好的解决方案,除了公开所有数据:-)。