使用私有成员复制javascript对象

时间:2010-10-13 22:13:09

标签: javascript object clone private

我四处张望,没有找到任何帮助我。为什么我不能用私有成员克隆一个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困住了吗?

4 个答案:

答案 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.");
}