js中对象和数组的浅拷贝与深拷贝(ES6、前端面试常用)

在ES6中扩展操作符(…)与Object.assign()中复制是浅拷贝,所谓的浅拷贝和深拷贝:

浅拷贝,是在拷贝过程中,遍历时那部分为对象/数组类型指向原来的地址。即修改其中任意的值,另一个值都会随之变化

深拷贝,则是完全开辟新的内存地址。即将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变

1、浅拷贝

浅拷贝: 只做一个最外层的拷贝. 如果拷贝的对象是引用型数据类型,则意味着交出了内存地址,因而在浅拷贝成功的对象身上对引用型数据进行修改时,就会影响到 原来的拓本

let obj = {
    a: 1,
    b: [1, 2, {a:3}],
    c: {a:3}
}
obj.c.a = 4

let obj1 = {
    a: obj.a,
    b: obj.b
}
obj1.b.push(1) // 切记不要 
obj1.b = 123 这样是重新赋值 不是改变原地址的对象
console.log(obj.b) //将会被改变


ES6方法:
let obj2 = Object.assign({},obj)
console.log(obj2)  //  {a: 1,b: [1, 2, {a:3}],c:{a:4}

let obj3 = {...obj}
conosle.log(obj3) //  {a: 1,b: [1, 2, {a:3}],c:{a:4}

 

2、深拷贝

深拷贝: 里里外外全部拷贝,完全复制,保证引用型数据 依旧是引用型,但不拿地址,只模仿你的面,因此扩展上没有问题,不会冲突

let obj1 = {
    a: 1,
    b: [1, 2, {a:3}],
    c: {a:3}
} 
//完全复制 完美复制 但是一个一个去复制,太麻烦啦 我们来一个专门深浅复制的函数

obj1.c.a = 4

let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2)  //    {a: 1,b: [1, 2, {a:3}],c:{a:3}

 

自制深复制函数

1.需求  参数1传入拓本  输出拷贝品
 let obj = { //拓本
     a: 1,
     b: [1,2,3,{a: "我"}],
     c: {d: 5}
 }
 function extend (o1) {
     var obj1 = {}
     if (o1 instanceof Array) { //判断对象是否是数组
         obj1 = []
     }
     for(var key in o1){
         var value = o1[key] // 拓本中的值 
          // value内还有引用型数据&& value不为 null 则 需要对value这个对象 再进来 深拷贝一份 返回出来深拷贝后的值 
         // obj1[key] = extend(value) 
         if(typeof value ==="object" && value !== null){
             obj1[key] = extend(value) 
         }else{
             obj1[key] = value
         }
     }
     return obj1
 }

let obj2 = extend(obj)  // 深拷贝测试
obj2.b.push("最后")
console.log(obj2)
console.log(obj) // 深拷贝 不影响拓本  浅拷贝 拓本一起变
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章