「JavaScript 深拷贝」你知多少?开发技巧+1✌️

98 阅读2分钟

🙏废话不多说系列,直接开整🙏

JavaScript-logo2.webp


1. 完整源码

核心功能:

  1. 方式一:使用遍历的方式;
  2. 方式二:防止两个对象是相互引用的;(升级版)
  3. 方式三:使用 JSON.parse 和 JSON.stringify(普遍性的拷贝方法);
// 方法一:使用遍历的方式
function deepCopy(obj1) {
    var obj2 = Array.isArray(obj1) ? [] : {};
    if (obj1 && typeof obj1 === "object") {
        for (var i in obj1) {
            if (obj1.hasOwnProperty(i)) {
                // 如果子属性为引用数据类型,递归复制
                if (obj1[i] && typeof obj1[i] === "object") {
                    obj2[i] = deepCopy(obj1[i]);
                } else {
                    // 如果是基本数据类型,只是简单的复制
                    obj2[i] = obj1[i];
                }
            }
        }
    }
    return obj2;
}
// 升级:(防止两个对象是相互引用的)
function deepCopy(obj1) {
    var obj2 = Array.isArray(obj1) ? [] : {};
    if (obj1 && typeof obj1 === "object") {
        for (var i in obj1) {
            var prop = obj1[i]; // 避免相互引用造成死循环,如obj1.a=obj
            if (prop == obj1) {
                continue;
            }
            if (obj1.hasOwnProperty(i)) {
                // 如果子属性为引用数据类型,递归复制
                if (prop && typeof prop === "object") {
                    obj2[i] = (prop.constructor === Array) ? [] : {};
                    arguments.callee(prop, obj2[i]); // 递归调用
                } else {
                    // 如果是基本数据类型,只是简单的复制
                    obj2[i] = prop;
                }
            }
        }
    }
    return obj2;
}

// 方法二:使用 JSON.parse 和 JSON.stringify(普遍性的拷贝方法)
var b = JSON.parse(JSON.stringify(a));


// 方法三:
/**
 * @param {object/array}  数组或对象
 * @return {object/array} 数组或对象
 */
function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj == {}) {
        return obj;
    }
    let result;
    if (obj instanceof Array) {
        result = [];
    } else {
        result = {};
    }

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = deepClone(obj[key]);
        }
    }

    return result;
}
// 实例1:深拷贝数组
let arrDemo = [1,2,3];
let arrDemoCloned = deepClone(arrDemo);
arrDemoCloned.push(4);
console.log(arrDemo); // [1, 2, 3]
console.log(arrDemoCloned); // [1, 2, 3, 4]
// 实例2:深拷贝对象
let objDeepTree = {
    name: "Drew",
    age: 23,
    habbit: {
        pingpang: "乒乓球",
        basketball: "篮球",
        football: "足球"
    }
}
let objDeepTreeCloned = deepClone(objDeepTree);
objDeepTreeCloned.sex = "男"
objDeepTreeCloned.habbit.internet = "网络"
console.log(objDeepTree); // {"age":23,"habbit":{"basketball":"篮球","football":"足球","pingpang":"乒乓球"},"name":"Drew"}
console.log(objDeepTreeCloned); // {"age":23,"habbit":{"basketball":"篮球","football":"足球","internet":"网络","pingpang":"乒乓球"},"name":"Drew","sex":"男"}

2. 示例

(1)深拷贝——对象
let student = {
    id: 1,
    name: 'Drew',
    age: 23
}
// 方法一:使用 深拷贝函数
let deepStudent  = deepCopy(student);
deepStudent.sex = "男";
console.log(deepStudent); // {id: 1, name: "Drew", age: 23, sex: "男"}
console.log(student);// {id: 1, name: "Drew", age: 23}

// 方法二:使用 JSON 类
let deepStudentByJSON = JSON.parse(JSON.stringify(student));
deepStudentByJSON.sex = "女";
console.log(deepStudentByJSON); // {id: 1, name: "Drew", age: 23, sex: "女"}
console.log(student);// {id: 1, name: "Drew", age: 23}
(2)深拷贝——数组
let arr = [1,2,3];
// 方法一:使用  深拷贝函数
let deepArr = deepCopy(arr);
deepArr.push(4);
console.log(deepArr);
console.log(arr);
// 方法二: 使用 JSON 内置类
let deepArrByJSON = JSON.parse(JSON.stringify(arr));
deepArrByJSON.push(66);
console.log(deepArrByJSON);
console.log(arr);

反思

(1)如果一个对象的属性时多层次的呢?(此时需要 扩展 deepCopy 的拷贝层级关系了 => lodash 库了解下)

(2)如果一个对象中含有方法呢?(此时 JSON 类的方法就无效果了)

(3)lodash JS工具库的学习:www.jianshu.com/p/d46abfa4d…

🙏至此,非常感谢阅读🙏

JavaScript-logo2.webp