JS高阶 --浅拷贝和深拷贝

63 阅读2分钟

浅拷贝和深拷贝

浅拷贝

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象
  • 浅拷贝:除了第一层地址不共享属性和方法,第二层以及第二层以上有地址共享

深拷贝

  • 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象
  • 深拷贝:任何地址都不共享属性和方法

浅拷贝的方法

对象的浅拷贝方法(2个)

  • Object.assign()
  • { ...obj }
var person = {
    name:"老刘",
    age:50,
    child:{
        name:"小刘",
        age:20
    }
}

//浅拷贝
//方法1 可选
var newPerson=Object.assign({},person);
//方法2 可选
var newPerson = {...person}
person.name ="老老老刘";
person.child.name = "小小小刘";

console.log(person === newPerson);//false
console.log(person.child === newPerson.child);//true

数组的浅拷贝方法(4个)

  • [ ...arr ]
  • arr.slice(0)
  • [].concat(arr)
  • arr.filter(item=>item)
var arr =["00",["11",22],{id:1234,name:" 1334"}]

//方法1 可选
var arr1 = [...arr]
//方法2 可选
var arr1 = arr.slice(0);
//方法3 可选
var arr1 = [].concat(arr);
//方法4 可选
var arr1  = arr.filter(item=>item);

arr1[0] = "99";
arr1[1][0] = "zzz";
console.log(arr);
console.log(arr1);

第三方插件库 _.clone()

lodash.js

  • 使用:通过lodash的_.clone,实现浅拷贝,数组与对象的浅拷贝
//使用lodash的_.clone,实现浅拷贝,数组与对象的浅拷贝
        var arr = [11,[22,33,44],55]
        var arr1 = _.clone(arr);
        arr[1][0] = "zzzz";
        arr[0] = "aaa";
        console.log(arr);
        console.log(arr1);

        var obj = {id:1,name:"刘华",child:{id:22,name:"小小刘"}}
        var obj1 = _.clone(obj);
        obj.name="zzz";
        obj.child.name = "ffff";
        console.log(obj);
        console.log(obj1);


深拷贝的方法(3个)

js提供的深拷贝方法

  • js提供的深克隆的方法,不完美
  • JSON.stringify 和 JSON.parse能够实现深克隆,但是会丢失方法
    var  person = {
             id:1,
             name:"刘德华",
             show(){},
             child:{
                 id:11,
                 name:"小花"
             }
         }
    
         var person2 = JSON.parse(JSON.stringify(person));
         console.log(person); 
         console.log(person2); //方法丢失
    
    

通过手写递归实现深拷贝

//自己写深克隆(递归)
     var person0 = {
         id: 1, name: "蔡徐坤",
         show() { },
         child: { id: 11, name: "小刘" }
     }

     //使用递归
     function deep(o) {
         let temp;
         if (Object.prototype.toString.call(o).includes("Object")) {
             temp = {}
         } else if (Object.prototype.toString.call(o).includes("Array")) {
             temp = []
         }
         for (let key in o) {
             if (Object.prototype.hasOwnProperty.call(o, key)) {
                 if (typeof o[key] == "object") {
                     temp[key] = deep(o[key])
                 } else {
                     temp[key] = o[key]
                 }
             }
         }
         return temp;
     }

     //克隆对象
     var person1 = deep(person0);
     person1.child.name = "aaaa";
     console.log(person1);
     console.log(person0);

     //克隆数组
     var arr0 = [11,[22,33],44];
     var arr1 = deep(arr0);
     arr0[1][0] = "aaaaa";
     console.log(arr0);
     console.log(arr1);

第三方插件库实现 _.cloneDeep()

lodash.js

  • 使用:通过lodash的_.cloneDeep(),实现深拷贝
 var person0 = {
            id: 1, name: "蔡徐坤",
            show() { },
            child: { id: 11, name: "小刘" }
        }
    
        var person1 = _.cloneDeep(person0);
        person1.child.name = "aaaaa"
        console.log(person0);
        console.log(person1);