其实文中提到的内容在MDN都有,只是大家可能没有留意到。建议直接看MDN原文。
我们知道做深拷贝的时候可以使用递归的方式也可以用JSON.stringify + JSON.parse
这种看起来简单的方式。
那么JSON.stringify + JSON.parse
这种方式真的好用吗?
文档告诉我:JSON.stringify + JSON.parse
做深拷贝不安全,而且在大数据量的情况下存在性能问题,不推荐使用(其实是JSON.stringify
的数据丢失)。
下面我们主要围绕不安全的问题进行讨论,对于性能的问题简单提下。
为何不安全
不安全主要体现在两个方面:
- 拷贝过程中数据失真、丢失(JSON.stringify的时候丢失)
- 处理特殊数据时候报错
数据失真、丢失
数据失真,丢失主要在这几种类型中有体现
Date对象拷贝后数据类型变成字符串
let obj = {
d: new Date(),
};
console.log(JSON.stringify(obj));
// {d: "2020-08-12T04:47:40.958Z"}
正则对象、Error对象拷贝后变成空对象
let obj = {
r: /\d+/gi,
e: new Error('an error')
};
console.log(JSON.stringify(obj));
// {r: {}, e: {}}
对象里面的函数和undefined属性、Symbol值拷贝后属性丢失
let obj = {
f: console.log,
u: undefined,
s: Symbol("foo")
};
console.log(JSON.stringify(obj));
// {}
NaN、Infinity、-Infinity拷贝后变为null
let obj = {
i: Infinity,
l: -Infinity,
n: NaN,
};
console.log(JSON.stringify(obj));
// {i: null, l: null, n: null}
改变对象的原型链
如果,对象的某个属性是由构造函数生成的,那么在拷贝后,他的constructor
会指向Object
。
var A = function () {
this.a = 'a';
};
var a = new A();
var b = JSON.parse(JSON.stringify(a));
console.log(a.constructor, b.constructor);
// ƒ () {this.a = 'a'} ƒ Object() { [native code] }
特殊数据报错
这个简单的说就是如果对象中有环的话话就会报错,最简单的例子就是
console.log(JSON.parse(JSON.stringify(window)));
这个就会报错,所以在使用这种方式做深拷贝的时候也要注意环的问题。
为何性能差
关于性能的问题我这里不多说,推荐《如何提升JSON.stringify()的性能》这篇文章,这篇文章对JSON.stringify
的性能问题说的很清晰,我也很认同。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。