Skip to content

Latest commit

 

History

History
88 lines (66 loc) · 2.46 KB

深度克隆与浅克隆.md

File metadata and controls

88 lines (66 loc) · 2.46 KB

深度克隆与浅克隆

要实现一个深度克隆,我们先了解JavaScript中数据类型:

  • 原始类型:Undefined,Null,Boolean,Number,String,Symbol
  • 引用类型:Object
浅克隆

浅克隆之所以被称为浅克隆,是因为对象只会被克隆最外部的一层,至于更为深层的对象,则依然是通过引用指向同一块堆内存


// 浅克隆函数
function shallowClone(o) {
  const obj = {};
  for ( let i in o) {
    obj[i] = o[i];
  }
  return obj;
}
// 被克隆对象
const oldObj = {
  a: 1,
  b: [ 'e', 'f', 'g' ],
  c: { h: { i: 2 } }
};

const newObj = shallowClone(oldObj);
console.log(newObj.c.h, oldObj.c.h); // { i: 2 } { i: 2 }
console.log(oldObj.c.h === newObj.c.h); // true


Object.assign()可以实现同样的功能

深克隆
JSON.parse方法
const newObj = JSON.parse(JSON.stringify(oldObj));
  

问题:

  • 无法实现对函数,RegExp,undefined,symbol等特殊值的克隆
  • 会抛弃对象的constructor,所有的构造函数会指向Oject
  • 对象有循环引用,会报错
递归
    var obj = {
        a: 10,
        b: 20,
        omg: {
            name: 'xuguojun',
            sex: 'male'
        }
     } 
     function deepcopy(obj){
        var newobj = {};
        for(arr in obj){
            if (typeof obj[arr]==='object' && obj[arr] !== null) {
                newobj[arr] = deepcopy(obj[arr]); //递归,核心代码
            } else {
                newobj[arr] = obj[arr];
            }
        }
        return newobj;
     }
     obj2 = deepcopy(obj);
     console.log(obj2); 
     obj2.omg.name = 'PDD'; 
     console.log(obj2.omg.name); 
     console.log(obj.omg.name);

当然,我们这个深克隆还不算完美,例如Buffer对象、Promise、Set、Map可能都需要我们做特殊处理,另外对于确保没有循环引用的对象,我们可以省去对循环引用的特殊处理,因为这很消耗时间,不过一个基本的深克隆函数我们已经实现了

在生产环境中最好用[lodash][https://github.com/lodash/lodash]的深克隆实现.