js深浅拷贝

1、在说深浅拷贝前,我们先来看看下面两个例子
在这里插入图片描述
在第一个列子里面,修改b的值并不会影响到a的值,在例子2 arr2修改里面的值时,会影响到arr1里面的值。同样是变量为什么表现不一样呢?这时候我们就要了解一下js中的数据类型:基本数据类型和引用数据类型
基本类型和引用类型
ECMASCRIPT的变量包含两种数据类型,基本数据类型和引用数据类型,基本数据类型指的是,保存在栈中的简单数据类型,引用数据类型则是保存在堆内存中的对象,也就是说变量中保存的是指向该对象的指针
基本数据类型包括:number string boolean undefined null
引用数据类型:array object function
因此看回之前的那个例子,例子1为基本数据类型,例子2为引用数据类型,所以深浅拷贝指存在于引用数据类型里
深拷贝与浅拷贝
如何实现深拷贝呢?
array和object看看他们自带的一些方法能不能实现深拷贝
先来看看array自带的一些方法
在这里插入图片描述
修改arr4并没有影响到arr3 通过slice()方法可以实现深拷贝 concat()和Array.from()同样可以达到这样的效果
好了,看完一维数组,我们再来看看二位数组
在这里插入图片描述
二维数组里面,通过slice();方法来拷贝,修改arr4的时候,arr3也跟着修改,总结:slice()对二维数组进行深拷贝是不可行的
object
1、assign()

在这里插入图片描述
经上面测试得到,assign()只对一维对象的深拷贝有用,二维对象没有效果
2、JSON.parse(JSON.stringify(obj));
在这里插入图片描述
JSON.parse(JSON.stringify(obj));可以满足90%的需求,对于含有function undefined symbol的对象进行不了深拷贝
那么我们就要用到我们的神器:递归

function deepcopy(obj){
         var result =(obj instanceof Array)?[]:{};
        for(let key in obj){
            if (obj[key] && typeof obj[key]=="object") {
                result[key] = deepcopy(obj[key]);
            }else{
                result[key] = obj[key];
            }
        }
        return result;
    }
    var obj1 = {
        x: 1,
        y: 2
    };
    obj1.z = obj1;
    console.log(obj1);
    var obj2 = deepcopy(obj1);
    console.log(obj1);
    console.log(obj2);
### JavaScript 深拷贝与浅拷贝的区别及实现方式 #### 深拷贝与浅拷贝的区别 浅拷贝仅复制对象的第一层属性,而深拷贝会递归地复制对象的所有层级。如果对象的属性本身是引用类型(如数组或对象),浅拷贝只会复制引用地址,而不会创建新的独立对象[^2]。 例如,使用浅拷贝时,修改原始对象中的嵌套对象会影响拷贝后的对象,因为它们共享相同的引用地址[^4]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = Object.assign({}, obj1); // 浅拷贝 obj2.b.c = 3; console.log(obj1.b.c); // 输出 3 ``` 相比之下,深拷贝会为嵌套的对象创建全新的实例,确保修改拷贝后的对象不会影响原始对象[^4]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝 obj2.b.c = 3; console.log(obj1.b.c); // 输出 2 ``` #### 实现浅拷贝的方法 1. 使用 `Object.assign()` 方法可以实现浅拷贝,它将源对象的属性复制到目标对象中[^4]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = Object.assign({}, obj1); ``` 2. 使用扩展运算符 `...` 也可以实现浅拷贝[^4]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = { ...obj1 }; ``` #### 实现深拷贝的方法 1. **递归实现**:通过递归遍历对象的每个属性,逐一复制。这种方法适用于复杂对象结构,但需要处理循环引用问题[^3]。 ```javascript function deepCopy(obj) { if (obj instanceof Array) { var newObj = []; } else { var newObj = {}; } for (let i in obj) { if (typeof obj[i] === "object" && obj[i] !== null) { newObj[i] = deepCopy(obj[i]); } else { newObj[i] = obj[i]; } } return newObj; } ``` 2. **通过 `JSON` 对象实现深拷贝**:将对象转换为字符串后再解析为新对象。此方法简单高效,但无法处理函数、`undefined` 和 `Date` 类型等特殊值[^2]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = JSON.parse(JSON.stringify(obj1)); ``` 3. **通过 jQuery 的 `extend` 方法实现深拷贝**:设置第一个参数为 `true` 即可启用深拷贝功能。 ```javascript let array = [1, 2, 3, 4]; let newArray = $.extend(true, [], array); ``` 4. **使用第三方库(如 Lodash)实现深拷贝**:Lodash 提供了 `_.cloneDeep` 方法,能够处理更复杂的对象结构[^1]。 ```javascript let obj1 = { a: 1, b: { c: 2 } }; let obj2 = _.cloneDeep(obj1); ``` 5. **改进的递归实现**:通过引入 `WeakMap` 处理循环引用问题,确保深拷贝的健壮性[^4]。 ```javascript function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (typeof obj !== "object") return obj; if (hash.has(obj)) return hash.get(obj); let cloneObj = new obj.constructor(); hash.set(obj, cloneObj); for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; } ``` #### 注意事项 - 浅拷贝仅适用于简单对象,对于嵌套对象可能引发意外行为。 - 深拷贝需要考虑性能问题,尤其是在处理大型或复杂对象时。 - 特殊类型(如 `Date`、`RegExp`、`Function`)在深拷贝时需要额外处理[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值