JS数组深拷贝、对象深拷贝

写在前面

为什么要做深拷贝?

        简而言之,这是由于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)

暂时总结到这!!!转载请注明出处


版权声明:本文为qq_2411868438原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。