在尝试多种用于JSON序列化对象的深度比较和复制实现后,我注意到最快的通常是:
function deep_clone(a){
return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
return JSON.stringify(a) === JSON.stringify(b);
};
我感觉这样是作弊,会有一些问题在未来困扰着我。使用这些是否可以?
在尝试多种用于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
比较可行。 - last-childJSON.stringify({ a: 1, b: 2 }).split("").sort().join("") === JSON.stringify({ b: 2, a: 1 }).split("").sort().join("")
- wmikJSON.stringify({ a: 12, b: 12 }).split("").sort().join("") === JSON.stringify({ b: 11, a: 22 }).split("").sort().join("")
期望的是false,但得到的是true。 - Jobin Mathew我知道这是一个老问题,但我想在答案中再添加一些内容,因为有些人可能会错误地认为只要不用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}
即使在没有订单问题的情况下(正如其他人所说,这可能是一个问题),这些怪癖也可能会引起麻烦。在大多数情况下,这些怪癖不太可能出现,但了解它们是很好的,因为它们可能导致一些难以找到的错误。
Infinity
、NaN
以及其他不属于JSON格式的值相比,包含函数、window
对象、undefined
、正则表达式等对象同样不相关。请注意保留原意,使语言更加通俗易懂。 - last-child==
)来比较两个从JSON.stringify
中获取的字符串。 - r gfunction 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
}
}