Javascript 使用JSON.stringify进行深度比较和克隆是否合适?
在尝试了几个实现来对JSON可序列化对象进行深入比较和复制之后,我注意到最快的实现通常是:Javascript 使用JSON.stringify进行深度比较和克隆是否合适?,javascript,json,equality,deep-copy,object-comparison,Javascript,Json,Equality,Deep Copy,Object Comparison,在尝试了几个实现来对JSON可序列化对象进行深入比较和复制之后,我注意到最快的实现通常是: function deep_clone(a){ return JSON.parse(JSON.stringify(a)); }; function is_equal(a,b){ return JSON.stringify(a) === JSON.stringify(b); }; 不过我觉得这是作弊。就像我会发现一些未来会困扰我的问题。可以使用这些吗?只要键值对始终处于相同的顺序,是的,您可
function deep_clone(a){
return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
return JSON.stringify(a) === JSON.stringify(b);
};
不过我觉得这是作弊。就像我会发现一些未来会困扰我的问题。可以使用这些吗?只要键值对始终处于相同的顺序,是的,您可以使用stringify来使用deep equals操作符(==)进行比较。JavaScript不保证键的顺序 如果它们以相同的顺序输入,这种方法在大多数情况下都会起作用,但并不可靠 此外,对于完全相等但其键以不同顺序输入的对象,它将返回false:
JSON.stringify({ a: 1, b: 2}) === "{"a":1,"b":2}"
JSON.stringify({ b: 2, a: 1}) === "{"b":2,"a":1}"
我意识到这是一个老问题,但我只是想补充一点答案,因为有人可能会离开本页,错误地认为使用
JSON.stringify
进行比较/克隆是可行的,只要它不用于比较/克隆成员无序的对象。(公平地说,对于公认的答案,他们不应该离开,认为这样做;它说,“如果[成员]以相同的顺序输入,这种方法在大多数情况下都会起作用。”)
代码可能最能说明潜在的问题:
JSON.stringify(NaN) === JSON.stringify(null)
// => true
JSON.stringify(Infinity) === JSON.stringify(null)
// => true
// or, to put it all together:
JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }) === JSON.stringify({ val1: NaN, val2: null, val3: null })
// => true
// and here's the same example with "cloning" rather than comparison:
JSON.parse(JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }))
// => Object {val1: null, val2: null, val3: null}
即使订购不是问题(正如其他人所说,这可能是问题),这些怪癖也会造成麻烦。在大多数情况下,这些怪癖不太可能会出现在他们丑陋的脑袋里,但意识到它们是件好事,因为它们可能会导致一些很难找到的bug。我只使用JSON serializable objects.FWIW文章严格要求使用“JSON object”,并声明没有“JSON object”这样的东西@BenjaminGruenbaum不完全重复,但是这些家伙还是在使用旧的JSON库。@DanC那么我怎么称呼JSON可序列化对象呢?很公平,在这种情况下没有问题。是的。这使得另一个答案是错误的。在最近的版本中,Javascript确实保证了密钥顺序。有关概述,请参见例如。实际上,JS引擎已经在这样做了。我认为既然现在定义了键顺序,两个具有不同顺序的相同键的对象不应该被视为等价的。因此,
JSON.stringify
比较有效。有人尝试过使用排序吗?类似于JSON.stringify({a:1,b:2}).split(“”.sort().join(“”===JSON.stringify({b:2,a:1}).split(“”.sort().join(“”)@wmik排序将不起作用。考虑这个例子<代码> JSON.StrugI化({a:12,b:12 }).Sead(“”)=(=)= JSON.StrugI化({B:11,A: 22 }).Seple(“”).SoTo():“连接”(“”)< /C>问题是关于“JSON可序列化对象的深度比较和复制”,因此Infinity
、NaN
和其他不属于JSON的值实际上与包含函数、窗口
对象、未定义的
、正则表达式等的对象没有任何关系……这是严格的等式,非深度相等运算符,您还可以使用常规相等(=
)来比较JSON.stringify