使用JSON可以吗?Stringify用于深度比较和克隆
Is it fine to use JSON.stringify for deep comparisons and cloning?
在尝试了几个json可序列化对象的深度比较和复制实现后,我注意到最快的通常只是:
function deep_clone(a){
return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
return JSON.stringify(a) === JSON.stringify(b);
};
我觉得这是作弊。就像我将来会发现一些困扰我的问题。用这些可以吗?
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。
只要键值对总是按相同的顺序,是的,您可以使用stringify使用深层相等操作符(===)进行比较。
我写了这个函数来深度比较任何对象数组或值:如果你想使用它:)我用对象和数组中随机输入顺序的非常大的对象样本来测试它。
function c(x, y) {
if (!x && !y) return !0
if (!x || !y) return !1
if (typeof (x) !==
typeof (y)) return !1
if (x instanceof Array) {
if (
x.length != y.length) return !1
const f = []
for (let i = 0; i < x.length; i++) {
if (!c(x[i], y[i])) f.push(i)
}
const g = [...f]
for (const i of f) {
let r = !1
for (const j of g) {
if (
c(x[i], y[j])) {
g.splice(g.indexOf(j), 1)
r++
break
}
}
if (!r) { return !1 }
}
return !0
} else if (x instanceof Object) {
const e1 =
Object.entries(x)
try {
return c(e1, r(Object.entries(y),
e1))
} catch (e) {
return !1
}
} else {
return x === y
}
function r(
u, v) {
const a = []
if (u.length != v.length) return u
for (
let i = 0; i < v.length; i++) {
a.push(m(u, v[i][0]))
}
return a
}
function m(a, k) {
for (let i = 0; i < a.length; i++) {
if (a[i][0] === k) return [a[i][0], a[i][1]]
}
throw 0
}
}
相关文章:
- 比较从函数和生成的日期对象
- 如何使用 node.js 比较两个 json 数组
- jQuery自定义验证比较多个输入的序列
- 反向字符串比较
- 通过JSON&比较时间
- 递归深度比较
- 与 lodash 进行对象深度比较的数组
- Javascript 深度比较
- 角度深度比较对象(特定属性除外)
- JS深度比较2个对象并删除在第二个对象中找到的项目,而不是第一个
- Javascript -深度相等比较
- 是否有一个实用程序来深度比较对象在谷歌闭包库
- 存储在Mongo中的数组无法与具有相同长度和值的本地javascript数组进行深度断言比较
- 初学者- Javascript中的深度比较
- Angular进行深度比较,并返回每一项的差值
- 使用JSON可以吗?Stringify用于深度比较和克隆
- 深度比较(Eloquent Javascript第4章):代码在测试用例中失败
- Javascript:深度比较
- 深度递归比较:对象和属性
- 这个柜台的功能是什么?雄辩的JavaScript 4.4深度比较的例子