深拷贝和浅拷贝

131 阅读2分钟

浅拷贝

浅拷贝是指复制对象的时候,指对第一层键值对进行独立的复制

function shallowCopy(target){
  if(!target || typeof target !== 'object'){
    return 
  }
  
  let newObj = Array.isArray(target)? []:{}
  
  for(var key in target){
    if(target.hasOwnProperty(key)){
      newObj[key]= target[key] 
    }
  }
  return newObj
}

传入数组成功

var arr = [1,2,3,4,5]

var arr2 = shallowCopy(arr)
console.log(arr2);//[1, 2, 3, 4, 5]

obj2[1] = 'js'
console.log(arr) //[1, 2, 3, 4, 5]
console.log(arr2)[1, "js", 3, 4, 5]

传入对象时成功

var obj = {
  "name" :'zhao',
  "age":16,
  'j':[1,2,3,4,5]
}

var obj2 = shallowCopy(obj)
console.log(obj2)

但是遇到一个问题

var obj2 = shallowCopy(obj)
console.log(obj2);
obj2.skill.a = 'js'
obj2.name = 'xiaoz'
console.log(obj.name)
console.log(obj2.name)
console.log(obj.skill.a)
console.log(obj2.skill.a)

对于skill这个属性,obj2变量复制的是它在堆中的地址,这也导致了obj和obj2的skill其实是指向堆中的同一个对象。 如果想要更深层次的拷贝,就需要用到深拷贝了

深拷贝

深拷贝还可以利用JSON的方式。

JSON.parse(JSON.stringify(obj));

对于一般的需求是可以满足的,但是它有缺点。下例中,可以看到JSON复制会忽略掉值为undefined以及函数表达式。

var obj = {
"name" :'zhao',
"age":16,
'j':[1,2,3,4,5],
"c":undefined,
"skill":{
  'a':'css'
},
 sum: function() { return age; }
}

var obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); 
/* [object Object] {
age: 16,
j: [1, 2, 3, 4, 5],
name: "zhao",
skill: [object Object] {
  a: "css"
}
}*/

深拷贝

deepCopy = (target )=>{
 if(!target || typeof target !== 'object'){
   return 
 }
 
 let newObj = Array.isArray(target)?[]:{};
 
 for(let key in target ){
  //判断类型
   if(typeof target[key] === 'object'){
     
     if(Array.isArray(target[key])){
       //是数组
        
     newObj[key] = target[key].map(item=>this.deepCopy(item))
     }else{
       //是对象
       //递归
       newObj[key] = this.deepCopy(target[key])
       
     }
     
   }else if(typeof target[key] === 'function'){
   //递归

    newObj[key] = target[key].bind(newObj)
   }else{
     newObj[key] = target[key]
   }
   
 }
 return newObj
 
}

 const obj = {
 a: 1,
 b: {a:1},
 c: { d: {b:1}, g: () => {console.log('hi')} },
 e: () =>{console.log('112')},
 f: function () {}
}

let obj2 = deepCopy(obj)
obj.c.d.b = '222'
console.log(obj.c.d.b) //"222"
console.log(obj2.c.d.b) //1

深拷贝成功