我四处张望,没有找到任何帮助我。为什么我不能用私有成员克隆一个javascript对象而不让它们量子纠缠?
看看这段代码......这是一个带有getter和setter的普通私有属性。 不知何故,如果我在一个实例上调用公共setter,克隆的一个也会被更改。为什么?可以解决吗?
obj = function(){
var changed = 0;
this.getChanged = function(){
return changed;
}
this.setChanged = function(){
changed = 1;
}
this.setUnchanged = function(){
changed = 0;
}
};
myObj = new obj();
copiedObj = $.extend(true, {}, myObj); // Or any other deep copy function you'd have around
myObj.setChanged();
myObj.getChanged(); // returns 1
copiedObj.getChanged(); // returns 1!
copiedObj.setUnchanged();
copiedObj.getChanged(); // returns 0
myObj.getChanged(); // returns 0
感谢任何想法。
编辑:到目前为止,没什么新内容。我知道javascript并没有像Java或C ++这样的OO,但是我们谈论的是编程语言,总有一条出路。有时它很丑,但有一个。
我明白了。
解决方案A:只需将其设为 this.changed ,而不是 var changed
解决方案B:制作我自己的克隆函数,重新重建整个对象
我只是希望有一些解决方案C可以将javascript引入标准的面向对象模式。
有人,我真的被A或B困住了吗?
答案 0 :(得分:3)
问题是已更改不是私有变量 - JavaScript没有私有变量。它是您为 obj 变量指定的函数的局部变量。当您创建分配给 getChanged / setChanged / setUnchanged 属性的函数时,您创建的closures已关闭在变量已更改。
当您克隆 myObj 时,您只是为这些功能创建了额外的别名。所以,无论你是通过 myObj 还是 copiedObj 访问它们,你仍然会调用相同的函数,并且因为它们是闭包,所以你访问的完全相同<在这两种情况下,strong>已更改变量。由于您无法复制功能,因此最好不要将更改设为私有,而只是在第二行执行 this.changed = 0; 。
答案 1 :(得分:1)
用作构造函数的函数中的局部变量称为“私有成员”,因此Java群众可以理解使用的意图。它不像财产一样工作。它是词法范围内的局部变量。它对实例是“私有的”,而不是类。 javascript中没有类。
最好的办法是添加一个克隆方法,深度复制实例。
答案 2 :(得分:1)
即使是深层副本也无法将函数复制为除引用之外的任何内容。由于你的功能是闭包,它们都共享相同的私人成员。为什么不写一个clone()
方法?
答案 3 :(得分:0)
得到了答案。
gilly3的提示有所帮助。
我实际使用的克隆/深拷贝函数不是jQuery,而是A. Levy posted on a similar question。
不得不以两种方式调整它以按照我的预期工作。事实上,原作者在他的解释中指出了方法,但在我第一次阅读时我没有抓住它 首先,我使用原始对象的构造函数和实例来实例化副本 过滤掉for for循环中的函数。
这是结果。希望有所帮助。
function clone(obj) {
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; ++i) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object (functions are skipped)
if (obj instanceof Object) {
var copy = new obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr) && !(obj[attr] instanceof Function)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}