# 手写深拷贝
在 js
中,由于数据存储方式不同,对于引用数据而言,分为浅拷贝和深拷贝。浅拷贝为只是对堆数据的地址进行拷贝,而深拷贝是对引用数据的内容进行拷贝。
# 浅拷贝
let obj = {foo: {foo: 'foo'}, bar: 'bar'};
let arr = [1,2,3];
let obj1 = obj; // obj1的任意修改都会影响到obj
let obj2 = Object.assign({}, obj); // 只能实现一层的深拷贝
let obj3 = {...obj}; // 只能实现一层的深拷贝
let arr1 = arr;
let arr2 = arr.concat([4,5,6]); // [1,2,3,4,5,6]
let arr3 = arr.slice();
let arr4 = [...arr]
# 深拷贝
深拷贝是将引用类型赋值真实的数据,而不仅是赋值一个引用地址。
# JSON.stirngify()
最简单的就是通过JSON.parse(JSON.stringify(obj))
let obj = {foo: {foo: 'foo'}, bar: 'bar'};
JSON.parse(JSON.stringify(obj));
# 手写clone
深度优先一直遍历, 最后返回一个新对象
// 判断是否是引用类型
let isObj = (obj) => {
return (typeof obj === 'object' || typeof obj === 'array') && obj !== null;
}
let clone = (obj) => {
let tem = Array.isArray(obj) ? [] : {};
for(let key in obj) {
tem[key] = isObj(obj[key]) ? clone(obj[key]) : obj[key];
}
return tem;
}
完善环、日期、正则不支持拷贝
let isObj = (obj) => {
return (typeof obj === 'object' || typeof obj === 'array') && obj !== null;
}
// hash为避免循环引用
let clone = function(obj, hash = new WeakMap()) {
let tempobj, constructor
constructor = obj.constructor
// RegExp Date单独处理
switch (constructor) {
case RegExp:
tempobj = new constructor(obj)
break;
case Date:
tempobj = new constructor(obj)
break;
default:
if (hash.has(obj)) return hash.get(obj)
tempobj = Array.isArray(obj) ? [] : {}
hash.set(obj, tempobj) // 这里现在是空的 可是后面的修改会影响这里
}
for (let key in obj) {
tempobj[key] = isObj(obj[key]) ? clone((obj[key]), hash) : obj[key]
}
return tempobj
}