21、js - 面试 - 深拷贝

文章探讨了JavaScript中实现深拷贝的几种方法,包括使用JSON.parse和JSON.stringify、lodash的_.cloneDeep方法、全局的structuredClone以及自定义递归函数。每种方法的优缺点也被详细说明,例如JSON.stringify会丢失undefined和函数属性,而_.cloneDeep需要引入额外库,structuredClone无法克隆方法,递归函数则可以灵活处理复杂对象和数组。
<script src="./lodash.min.js"></script>

<script>

    // 深拷贝
    const obj = {
        name: 'hello',
        age: 14,
        hi: undefined,
        eat: () => { },
        arr: [1, 2, 3, 4],
        min: {
            son: 'vite'
        }
    }

    // 1、序列化  反序列化  JSON.parse(JSON.stringify())
    // 缺点:属性值是undefined和function的属性会删除
    const newObj1 = JSON.parse(JSON.stringify(obj));
    newObj1.min.son = "pinia";
    // hi属性和eat属性被删掉了
    console.log(newObj1); // { "name": "hello", "age": 14, "arr": [1,2,3,4], "min": { "son": "pinia" } }

    // 2、lodash的 _.cloneDeep()
    // 不会删除属性
    // 缺点:需要引入第三方库
    const newObj2 = _.cloneDeep(obj);
    newObj2.min.son = "ts";
    console.log(newObj2);

    // 3、全局的structuredClone()
    // 缺点:对象的属性值时方法时会报错
    // const newObj3 = structuredClone(obj);
    // newObj3.min.son = "js";
    // console.log(newObj3); // Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': () => { } could not be cloned.
    console.log(obj);
 
    // 4、自己手写递归函数实现深拷贝
    const obj1 = {
        name: 'hello',
        test: {
            age: 12
        }
    }
    const arr = [1, 2, 3, { name: 'vite' }];

    function cloneDeep(oldObj) {
        const newObj = Array.isArray(oldObj) ? [] : {};

        for (let i in oldObj) {
            if (typeof oldObj[i] === 'object') {
                newObj[i] = cloneDeep(oldObj[i]);
            } else {
                newObj[i] = oldObj[i];
            }
        }

        return newObj;
    }

    const result1 = cloneDeep(obj1);
    result1.test.age = 15;
    console.log(result1);
    console.log(obj1);


    const result2 = cloneDeep(arr);
    result2[3].name = "ts";
    console.log(result2);
    console.log(obj);

</script>
### JavaScript 中浅拷贝与深拷贝的区别 #### 浅拷贝 (Shallow Copy) 浅拷贝创建一个新的对象,该新对象拥有原始对象属性值的一份副本。如果这些属性也是对象,则只复制其引用而不是创建新的实例。这意味着当修改嵌套对象的内容时,原对象和新对象会共享相同的内部对象。 在JavaScript中可以通过多种方式实现浅拷贝: - 使用 `Object.assign()` 方法[^1] - 利用扩展运算符 (`...`)[^4] ```javascript const obj1 = { a: 1, b: { c: 2 } }; // 浅拷贝例子 let shallowCopyObj = Object.assign({}, obj1); shallowCopyObj.b.c = 3; console.log(obj1); // 输出: { a: 1, b: { c: 3 } } ``` #### 深拷贝 (Deep Copy) 相比之下,深拷贝不仅复制最外层的对象结构,还会递归地遍历并克隆所有的子对象,从而确保两个对象之间没有任何关联。因此,在对任意层次上的任何部分进行改动都不会影响另一个对象的状态。 为了完成一次完整的深拷贝操作可以考虑如下几种方案: - JSON 序列化/反序列化技巧(适用于纯JSON可表示的数据) - 自定义函数处理循环引用等问题 - 第三方库如 lodash 的 _.cloneDeep() 函数 ```javascript const deepClone = structuredClone || ((obj) => { return JSON.parse(JSON.stringify(obj)); }); const obj2 = { d: 4, e: { f: 5 } }; let deepClonedObj = deepClone(obj2); deepClonedObj.e.f = 6; console.log(obj2); // 输出: { d: 4, e: { f: 5 } } ``` #### 面试常见问题 面试官可能会围绕以下几个方面提问关于浅拷贝和深拷贝的知识点: 1. 如何区分基本类型变量和引用类型的赋值行为? 2. 描述一下什么是浅拷贝以及它的工作原理是什么样的? 3. 给定一段代码片段,请指出其中存在的潜在风险,并说明为什么应该使用深拷贝代替浅拷贝。 4. 实现一个简单的深拷贝算法,考虑到特殊情况比如循环引用的情况如何解决?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值