【问题标题】:Copy javascript object with private member使用私有成员复制 javascript 对象
【发布时间】:2011-04-25 02:46:19
【问题描述】:

我环顾四周,找不到任何可以帮助我的东西。为什么我不能克隆一个带有私有成员的 javascript 对象而不使它们发生量子纠缠?

看看这段代码...它是一个带有getter 和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?

【问题讨论】:

    标签: javascript object clone private


    【解决方案1】:

    函数中用作构造函数的局部变量被称为“私有成员”,因此Java 大众可以理解使用的意图。它不像财产那样工作。它是词法范围内的局部变量。它是实例的“私有”,而不是类。 javascript 中没有类。

    最好的办法是添加一个克隆方法,该方法将深度复制实例。

    【讨论】:

      【解决方案2】:

      即使是深拷贝,也不能将函数复制为引用。而且由于您的函数是闭包,它们都共享相同的私有成员。为什么不写一个clone() 方法呢?

      【讨论】:

        【解决方案3】:

        问题在于 changed 不是私有变量——JavaScript 没有私有变量。它是您分配给 obj 变量的函数的局部变量。当您创建分配给 getChanged / setChanged / setUnchanged 属性的函数时,您将创建 closures变量改变了

        当您克隆 myObj 时,您只是为这些函数创建了额外的别名。因此,无论您是通过 myObj 还是 copiedObj 访问它们,您仍然调用相同的函数,并且因为它们是闭包,所以您访问的是完全相同的 改变了变量。由于您无法复制函数,因此最好不要尝试将 changed 设为私有,而只是在第二行执行 this.changed = 0;

        【讨论】:

          【解决方案4】:

          得到答案。

          gilly3 的提示有所帮助。

          我使用的克隆/深拷贝功能实际上不是 jQuery 的,而是 A. Levy posted on a similar question 的那个。

          必须以两种方式对其进行调整才能按我的预期工作。事实上原作者在他的解释中已经指出了方法,但我第一次阅读的时候并没有明白。
          首先,我使用原始对象的构造函数和
          从 for in 循环中过滤掉函数。

          这是结果。希望对某人有所帮助。

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

          【讨论】:

          • 请记住,您实际上并没有使用此方法克隆 changed 变量的值。如果这是一个要求,您将需要一个特定于您的 obj“类”的克隆方法,该方法使用 getChanged / setChanged 来传输值。
          • 是的。在我的情况下,更改的变量特定于实例,并且在构造函数中具有默认值。我不想被复制,所以没关系。谢谢。
          猜你喜欢
          • 1970-01-01
          • 2015-05-15
          • 1970-01-01
          • 2012-08-31
          • 1970-01-01
          • 2012-06-13
          • 2018-06-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多