【问题标题】:javascript deep copy using JSON使用 JSON 的 javascript 深拷贝
【发布时间】:2014-01-06 21:03:55
【问题描述】:

我对 javascript 对象(数组)深拷贝有问题。我读了很多处理它的好方法。而且我也知道 jQuery 有 $.extend API 来解决这个问题。但我的问题是:我可以只使用 JSON stringify 和 parse 方法来解决这个问题吗?

这是我的代码:

function deepCopy(oldValue) { 
  var newValue
  strValue = JSON.stringify(oldValue)
  return newValue = JSON.parse(strValue)
}

var a = {
  b: 'b',
  c: [1,2,4],
  d: null
}

copy = deepCopy(a)

console.log(a === copy) // false
console.log(a.c === copy.c) // false

PS:我知道如果不是所有对象都是可序列化的,但我知道的唯一情况是当对象包含一个函数属性时。还有其他情况吗?

【问题讨论】:

  • 并非所有对象都可以序列化为 JSON。即使是这样,将它们转换为字符串然后解析字符串似乎也是低效的。但它应该工作得很好。唯一的问题是旧版本的 IE,你需要一个 polyfill。
  • 谢谢!我只知道如果该对象包含作为函数的属性,则该对象不可序列化。但是如果其他情况是对象不可序列化呢?
  • 另一方面,相比普通方式,使用JSON深度复制对象真的效率低下吗?
  • 您的深层副本有效。 object comparison 正在正常工作。一切都好!

标签: javascript json deep-copy


【解决方案1】:

如果您的对象是“小”并且包含专门可序列化的属性,那么使用 JSON 序列化的简单 deepCopy hack 应该没问题。但是,如果您的对象很大,您可能会遇到问题。如果它包含不可序列化的属性,它们就会丢失:

var o = {
 a: 1,
 b: 2,
 sum: function() { return a + b; }
};

var o2 = JSON.parse(JSON.stringify(o));
console.log(o2);

产量:

Object {a: 1, b: 2}

有趣的是,C# 中相当多的深拷贝解决方案都是类似的序列化/反序列化技巧。

附录:不确定在比较复制后的对象方面您希望得到什么。但是,对于复杂的对象,您通常需要编写自己的Compare() 和/或Equals() 方法才能进行准确的比较。

同样值得注意的是,这种副本不保留类型信息。

JSON.parse(JSON.stringify(new A())) instanceof A === false

【讨论】:

  • 这是在 Chrome 控制台中快速调试的一个很好的解决方案,因为 Chrome 将始终显示对象的最终状态,而不是调用 console.log 函数时的状态。跨度>
【解决方案2】:

你可以这样做,但是由于上面列出的一些原因,它是有问题的:

  1. 我质疑性能。

  2. 你有任何不可序列化的属性吗?

  3. 最大的问题是:您的克隆缺少类型信息。取决于你在做什么,这可能很重要。实现者是否在原始对象的原型中添加了方法?那些都没了。我不确定你还会失去什么。

【讨论】:

    【解决方案3】:

    我认为您正在寻找的是这样的: 如果您有一个真正嵌套的对象结构,那么要进行深层复制,您可以使用 JSON.stringify()。

    请看下面的例子:

    var obj= {
          'a':1,
          'b':2,
          'c': {
            'd':{
              'e' : 3
            }
          }
        }
    
    
    var newObj = {...obj};
    var lastObj = JSON.parse(JSON.stringify(obj));
    obj.c.d.e =19;
    console.log('obj '+obj.c.d.e);
    console.log('newObj '+obj.c.d.e);
    console.log('lastObj'+lastObj.c.d.e); 
    

    现在 lastObj 真正与 obj 分离,而如果您使用 ...(spread) 运算符,它也不适用于真正复杂的对象。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 2011-09-05
      相关资源
      最近更新 更多