写在前面
为什么要做深拷贝?
简而言之,这是由于js定义的基础数据类型和复杂数据类型的本质决定的。基础数据类型存储在堆中,拷贝赋值引用的是值,修改拷贝后的值并不会影响原值;而复杂数据类型值存储在堆中,引用地址存储在栈中,拷贝赋值的是引用地址,修改拷贝后的值会修改原先的值。
有时候需要对copy的数据进行修改,但不想破坏原先的值,这就需要做深拷贝了。
具体实现
数组的深拷贝
方法一: 利用for循环+push
let arr = [1, 2, 3, 4, 5];
let resArr = [];
for(let i = 0; i <= arr.lenght - 1; i++){
resArr.push(arr[i])
}
console.log(resArr) //[1, 2, 3, 4, 5]
方法二: 利用slice截取特定范围内容不会影响原数据的方法
回忆一下slice方法:①slice数组,字符串都可用;②arr/str.slice(startIdx[包括],endNum[不包括]),例如对于上方数组里的arr,执行arr.[1,3],意思是截取从左往右数第1个元素(包含)到第3个元素它得到的结果是 [2, 3];省略end表示截取到末尾 ③负数代表从右往左数
let arr = [1, 2, 3, 4, 5];
let resArr= arr.slice(0);
console.log(resArr); //[1, 2, 3, 4, 5]
方法三: 利用concat合并空得到一个新数组
let arr = [1, 2, 3];
let resArr = arr.concat();
console.log(arr) //[1, 2, 3]
方法四:利用ES6数组的扩展运算符 ... 展开得到一个新数组
let arr = [1, 2, 3];
let arr1 = [...arr];
console.log(arr1) //[1, 2, 3]
当然还有简单粗暴 JOSN.parse(JSON.stringify(arr))
对象深拷贝
方法一:JSON.parse(JSON.stringify())
let obj = {name: '小明', age: 18};
let newObj = JSON.parse(JOSN.stringify(obj))
*需要注意的是,如果属性中有function则不能正确深复制
方法二:利用ES6 对象的Object.assign()方法,注意:也只能针对对象属性为基本类型的情况
let obj = {name: '小明', age: 18};
let obj2 = Object.assign({}, obj);
使用上面方法,只能克隆拷贝对象本身的值,而不能克隆继承的值,如果需要保持继承,使用下面方法:
let obj = {name: '小明', age: 18};
function cloneObj(originObj) {
let originObjProto = Object.getPrototypeOf(originObj);
return Object.assign(Object.create(originObjProto ), originObj)
}
let newObj = cloneObj(obj)
方法三:利用for循环遍历对象,并判断子属性扔就为对象时递归,需要时调用,完美克隆对象中的function
function cloneObj(obj) {
if (typeof obj !== 'object') {
return obj;
} else {
var newobj = obj.constructor === Array ? [] : {};
for (var i in obj) {
newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i];
}
return newobj;
}
}
cloneObj(需要深拷贝的obj)
暂时总结到这!!!转载请注明出处