面试经之深浅拷贝

90 阅读2分钟

首先要对其定义有点了解,先来说一下浅拷贝。

浅拷贝:拷贝的是指向对象的指针,本质上还是 指向同一对象的内存地址

 如:对象直接赋值后修改其属性,导致原来属性也跟着变化

 let obj={a:1,b:2};    
 let other=obj;             
 other.a=3;           
 console.log(obj)//{a:3,b:2} 

深拷贝:复制一个新的对象,在堆内存中是两个完全不同的内存地址

常见的实现方式如下:

1.object.assign({},obj) ;  方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 这个存在争议的拷贝方式,它可以说是深拷贝,也可以说是浅拷贝,不过,这些都是根据拷贝的对象结构所定,若拷贝层级为一级(简单类型如string, number)那么可以是深拷贝,若拷贝层级一级以上(属性值为对象或其它引用类型如object .array.function),那么则为浅拷贝。

// 一层深拷贝
let obj = {a:1};
let newObj = Object.assign({},obj);
console.log(newObj); //{a: 1}
newObj.a=2;
console.log(obj);//{a:1}
console.log(newObj); //{a: 2}

//二层浅拷贝
let obj = {a:1,b:{name:"zhangsan"}};
let newObj = Object.assign({},obj);
newObj.b.name="lisi";console.log(obj); //{a:1,b:{name:"lisi"}}
console.log(newObj); //{a:1,b:{name:"lisi"}}


2. JSON.parse(JSON.stringify(obj); JSON.stringify 将js对象序列化(JSON字串), JSON.parse来反序列化(还原)js对象,  针对二维的数据结构的对象,若遇到对象中含有函数或者正则以及undefined等值会丢失,由于JSON.stringify()只能序列化对象的可枚举的自有属性,如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;所以此方法需要确认对象中没有函数或正则才可用作深拷贝。

 let obj = {a:1,b:function(){},c:{d: 2},d:{regex:/^\s*/g, desc:'去掉字符串左侧空白字符正则'},
e:undefined}; 
console.log(obj);
let newObj=JSON.parse(JSON.stringify(obj));
console.log(newObj);



3.自定义深拷贝(递归方式)

const deepClone=(obj)=>{  
    if(typeof obj !=="object" || obj===null) return ; 
      let newObj=obj instanceof Array?[]:{};      
      for(let key in obj){                            
           new[key]=typeof obj[key] ==="object" && obj[key] !==null?
           deepClone(obj[key]):obj[key];                 
      }
     return newObj
}
 let obj = {a: 1, b: function(){}, c: {d: 2}}//deepClone(obj) 
  {a: 1, b: function(){}, c: {d: 2}}
//let obj=['a',2,'c',3];
//(deepClone(obj)//['a',2,'c',3]