所以我在一些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”,而我的功能正在访问全局上下文。但这似乎并非如此,所以我的下一个想法是它使用原型的变量local。这对我来说没有多大意义,因为原型的构造函数调用本地的变量不应该在它之外可访问,除非通过已经在范围内的方法访问它。当然,rootID()函数确实在范围内,但我的印象是它将使用调用对象的对象上下文而不是原型来运行。
所以,我很困惑。任何可以解决这个问题的光都会引起很多的感激。
编辑:PRB提供的文章描述了一个彻底解决这个问题的解决方案 - 主要是。本文指出您还需要从子类构造函数中调用父类的构造函数来正确初始化所有内容。因此,所有方法都是新创建的,并且在闭包时使用自己的父类本地变量版本。这种方法似乎确实存在一个缺点(除了每个实例中复制功能的效率问题)。如果试图从原型链中调用“重写”函数以尝试超级功能,则此问题将重新出现。像以前一样,原型是单个对象的实例,并且试图调用它们的函数版本将导致它们尝试访问它们的实例的局部变量。
除了公开所有数据外,我还看到了最好的解决方案: - )。
答案 0 :(得分:2)
使用此行可能是个问题:
this.prototype = new parentClass();
这意味着函数的所有实例共享由parentClass()定义的相同内存blob。这就是为什么当你在一个中更改值时,它会影响所有值。
答案 1 :(得分:0)
好吧,所以我一直在考虑吃晚餐,我想我可能会对正在发生的事情有所了解。我认为由于对象上下文的变化而导致函数可用的变量混乱,以及由于闭包而导致函数可用的变量。
正如PRB指出的那样,我的rootID()函数总是从实例化的原型中访问内存块。 _root_id被创建为我的基类的构造函数的本地变量,因此当该基类被实例化为原型时,使用原型函数的所有子类将因此读取/写入构造函数中创建的一个变量
因此,虽然这是创建原型的有效方法,但使用构造函数本地变量隐藏对象的数据将无法在子类中正常工作。相反,我需要读取/写入'this'中的变量,以便随着对象的上下文变化而变化。如果有人知道更好的方法来处理这个问题 - 一个服从数据隐藏的方法,请随时发表评论;很多与我合作的开发人员都没有关于直接访问数据成员而不是访问者的疑虑。使代码难以维护: - /。
无论如何,感谢PRB的澄清! ~Nate