js深浅拷贝

用处

当我们需要对一个引用值进行复制时,我们就需要用到拷贝

例子

原始值拷贝
    let a = 12
    let b = a
    a = 13
    console.log(b) // 打印出 12
引用值拷贝(错误版)

如果我们使用与原始值相同的拷贝方法就会出现以下结果

     let obj1 = {
        name: "小明",
        age: 17
     }
     let obj2 = obj1
     obj1.name = "小红"
     console.log(obj2.name) // 此时输出为小明

因为对 obj2 进行赋值时,仅仅复制了 obj1 的指针,而指针的指向仍然是同一个对象,所以当我们通过 obj1 改变的对象与 obj2 指向的对象是同一个对象;

浅拷贝
  • es3写法
 let obj1 = {
     name: "小明",
     age: 17
 }   
 function simpleClone(obj) {
   var cloneObj = {}
   // es3 的写法
   for(let i in obj) {
     cloneObj[i] = obj[i]
   }
   return cloneObj
 }
 let obj2 = simpleClone(obj1)
 obj1.name = "小红"
 console.log(obj2.name) // 小明
 console.log(obj1.name) // 小红
  • es6 写法
 let obj1 = {
     name: "小明",
     age: 17
 }   
 function simpleClone(obj) {
   var cloneObj = {}
   // for(let key of Object.keys(obj1)) {
   //   cloneObj[key] = obj1[key]
   // }
   for(let [key,value] of Object.keys(obj1)) {
       cloneObj[key] = value
   }
   return cloneObj
 }
 let obj2 = simpleClone(obj1)
 obj1.name = "小红"
 console.log(obj2.name) // 小明
 console.log(obj1.name) // 小红
深拷贝
  • 利用递归层层拷贝

 let obj1 = {
   a: 1,
   b: 3,
   c: {
     e: {
       f: 8
     },
       g: 4
   },
   h: 7
  }
function deepClone(obj,cloneObj) {
var cloneObj = cloneObj || {}
for(let i in obj) {
 if(typeof obj[i]=== 'object' && obj[i] !== null) {
   cloneObj[i] = {}
   deepClone(obj[i],cloneObj[i])
 } else {
   cloneObj[i] = obj[i]
 }
}
return cloneObj
}
let obj2 = deepClone(obj1)
obj1.c.g = 10
console.log(obj2.c.g) 

  • 利用 JSON.parse() 和 JSON.stringify 先将其转化为字符串,在重新转化为对象
	 let obj1 = {
       a: 1,
       b: 3,
       c: {
         e: {
           f: 5,
           i: [1,2,4,5]
         },
         g: 4
       },
       h: 7
     }
    function deepClone(obj,cloneObj) {
    // 利用 JSON.parse() 和 JSON.stringify  先将其转化为字符串,在重新转化为对象
      return JSON.parse(JSON.stringify(obj))
    }
    let obj2 = deepClone(obj1)
    obj1.c.e.i.push(10)
    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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值