使用JSON.stringify的方式来实现深拷贝的弊端
弊端一:无法拷贝NaN、Infinity、undefined这类值
无法拷贝成功的原因:
对于JSON来说,它支持的数据类型只有null、string、number、boolean、Object、Array,所以对于它不支持的数据类型就会自动转成null。
为什么undefined拷贝会丢失?
因为JSON不支持undefined这个数据类型,并且undefined相当于没有定义,所以就无法拷贝成功。
例如下图:我给obj.c设为undefined,但我没有给obj.tttttttttt设置任何值,它也是undefined。
弊端二:无法拷贝循环引用
什么是循环引用
如下图:目标对象的子孙属性中,赋值了目标对线,就会导致循环引用。
对循环对象使用JSON.stringify进行深拷贝时会出现报错
如下图所示:
解决方案
解决方案的话,一般就是使用第三方库的深拷贝方法处理啦。
不过下面我会介绍在自己手写深拷贝的时候,如何去解决循环引用问题(为了面试)。
先上代码:
function deepClone(target, mapObj = new WeakMap()) {let res;const typeStr = Object.prototype.toString.call(target);if(typeStr === '[object Object]') {res = {};} else if (typeStr === '[object Array]') {res = [];} else {return target;}Object.keys(target).forEach(key => {if(target.hasOwnProperty(key)) {if(typeof target[key] === 'object') {if (mapObj.get(target[key])) {res[key] = target[key]} else {mapObj.set(target[key], target[key]);res[key] = deepClone(target[key], mapObj);}} else {res[key] = target[key];}}})return res;
}
这里的话,主要是引用了weakMap来处理循环引用问题,因为weakMap支持key是一个对象。
手写deepClone的话,就无需兼容上面弊端一的问题了,因为js是支持NaN、Infinity这些数据类型的。