【问题标题】:Can someone explain me this javascript object "copy" behavior有人可以解释一下这个 javascript 对象“复制”行为吗
【发布时间】:2011-09-29 21:58:26
【问题描述】:

我有以下代码(我正在使用 jQquery 库):

var obj = {};
var objstring = '{"one":"one","two":"two","three":"three"}'

// first console output
console.log(objstring);

var jsonobj = $.parseJSON(objstring);

// second console output
console.log(jsonobj);

obj.key = jsonobj;
obj.key.test = "why does this affect jsonobj? (even in the second console output)";

// third console output
console.log(jsonobj);

我的问题: 当我执行 obj.key = jsonobj 并更改新 obj.key 中的值时。为什么 jsonobj 中的值也会发生变化?我将如何避免这种情况? (我想要一个 jsonobj 的新“副本”)。

我做了这个测试用例:http://jsfiddle.net/WSgVz/

【问题讨论】:

  • 格式完美的问题和测试用例。令人难以置信的是,如今这种情况如此罕见。

标签: javascript javascript-objects


【解决方案1】:

我想解决这里发生的一小部分问题,因为其他人已经很好地解决了 JavaScript 对象引用的更大问题:

// second console output
console.log(jsonobj);

obj.key = jsonobj;
obj.key.test = "why does this affect jsonobj? (even in the second console output)";

这是documented WebKit bug 的结果,即console.log 语句不会在调用console.log 时输出对象,而是在一段时间后输出。

【讨论】:

  • 我试图更清楚地说明我此时得到了什么,所以请解释任何 -1 票...
  • 哦,好吧,这只会导致我以前对 javascript 如何处理对象复制/委托的错误理解。感谢您指出这一点;)。
  • 将我的 -1 更改为 +1。在我投票时,您没有详细的答案。现在我脸上有鸡蛋。
【解决方案2】:

那是因为对象没有被复制。 obj.key 属性将只包含对该对象的引用,因此当您将某些内容分配给 obj.key.test 时,效果与将其分配给 jsonobj.test 相同。

您可以使用jQuery方法extend创建一个副本:

obj.key = $.extend({}, jsonobj);

这会将值复制到新创建的对象 ({})。

【讨论】:

  • 另外值得注意的是,您需要$.extend(true, {}, jsonobj) 进行深层复制(而不是浅层的一级复制)。
  • @Domenic:好点子,了解更复杂的对象结构是件好事。
【解决方案3】:

因为当您执行obj.key = jsonobj 时,obj.key 中没有新的复制对象;它只是对已经存在的jsonobj 的引用。所以对obj.key 的更改也会更改jsonobj,因为它们实际上是同一件事。

【讨论】:

    【解决方案4】:

    这是因为 没有进行复制 -- 只有一个对象,即 referenced 由各种变量和属性组成。当您执行obj.key = jsonobj 时,您只是将引用复制到同一个对象。

    【讨论】:

      【解决方案5】:

      JavaScript 中的所有对象都是通过引用复制的,意思是:

      var x = {};
      var y = x;
      x.foo = 22; // y.foo also = 22 since y and x are the same object
      

      如果你想要obj.key != jsonobj,你需要克隆对象。通过创建一个新对象:

      obj.key = $.parseJSON(objstring);
      

      或使用jQuery克隆现有的:

      obj.key = $.extend({}, jsonobj);
      

      【讨论】:

      • 但我似乎没有找到第二个日志输出背后的答案............
      • 第二条日志语句是错误的,根据 Domenic 的回答。如果你想要一个有效的 console.log:console.log(JSON.stringify(jsonobj))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 2017-09-02
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      相关资源
      最近更新 更多