深拷贝和浅拷贝实现方式

浅拷贝实现

1. for···in只循环第一层

// 只复制第一层的浅拷贝
function simpleCopy(obj1) {
   var obj2 = Array.isArray(obj1) ? [] : {};
   for (let i in obj1) {
   obj2[i] = obj1[i];
  }
   return obj2;
}
var obj1 = {
   a: 1,
   b: 2,
   c: {
         d: 3
      }
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4

2. Object.assign方法

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3

3.使用扩展运算符实现

对于引用数据类型,扩展运算符实现的是浅拷贝。

4.用=赋值实现

let arr1=[0,1,2,3,4],
    arr2=arr1;
console.log(arr1===arr2);
arr1[0]=1;
console.log(arr1,arr2);

深拷贝实现

1.递归实现

function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}   

2. JSON.stringify和JSON.parse实现

 var   obj1 = {
   a: 1,
    b: {
      c:2
    }
   }

  var obj2 = JSON.stringify(JSON.parse(obj1)),

弊端:
1).如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式;
2).如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
3).如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4).如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null

5).JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
6).如果对象中存在循环引用的情况也无法正确实现深拷贝;

3.通过jQuery的extend方法实现深拷贝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝

4.lodash函数库实现深拷贝

let result = _.cloneDeep(test)

5.Reflect法

// 代理法
function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }

    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [...obj] : { ...obj }
    Reflect.ownKeys(cloneObj).forEach(key => {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })

    return cloneObj
}

6.Object.assign ,针对对象的value是基本类型

如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象

var obj = {
    a: 1,
    b: 2
}
var obj1 = Object.assign({}, obj); // obj赋值给一个空{}
obj1.a = 3;
console.log(obj.a);// 1

7. 用slice实现对数组的深拷贝;用concat实现对数组的深拷贝

8 .使用扩展运算符实现(基本数据类型的拷贝)

// 当value是基本数据类型,比如String,Number,Boolean时,是可以使用拓展运算符进行深拷贝的
// 当value是引用类型的值,比如Object,Array,引用类型进行深拷贝也只是拷贝了引用地址,所以属于浅拷贝
var obj= {a: "1", b: "1", c: "2"}
var obj2= { ...obj, a: "5" }

9. 使用var newObj = Object.create(oldObj)

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

你可能感兴趣的:(深拷贝和浅拷贝实现方式)