浅拷贝 、深拷贝、对象赋值的区别?

538 阅读2分钟

什么是浅拷贝?什么是深拷贝?

这三者的区别如下,不过比较的前提都是针对引用类型

先说一个简单的概念,什么是对象赋值?

对象赋值

    1. 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
// 对象赋值:
        var obj={
           name:"xuxu",
           age:23
        }
        var obj2=obj;    //赋值  是  赋的栈中的地址;
        obj2.name='haha';
        console.log(obj.name);  //haha
        console.log(obj);       //{name:'haha',age:23}

浅拷贝

    1. 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

image.png 实例:

//2.浅拷贝  :
let obj = {
            name: 'xuxu',
            chi() {
                food: '肉'
            }
        }
        let obj3 = qian(obj);
        obj3.name = 'genggeng';
        obj3.chi.food = '菜'; // 新旧对象还是共享同一块内存
        function qian(item) {
            let obj2 = {};
            for (var i in item) {
// hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)
                if (item.hasOwnProperty(i)) {
                    obj2[i] = item[i];
                }
            }
            return obj2;
        }
        console.log('obj', obj);    //obj 
//Object
//  chi: ƒ chi()
//  name: "xuxu"
        console.log('obj3', obj3);  //obj3 
//Object
//  chi: ƒ chi()
//  name: "genggeng"

深拷贝

    1. 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

image.png

// 3.深拷贝
        // let obj1 = {
        //     name: 'xuxu',
        //     arr: [1, [2, 3], 4],
        // };
        // let obj4 = deepClone(obj1)
        // obj4.name = "gengeng";
        // obj4.arr[1] = [5, 6, 7]; // 新对象跟原对象不共享内存
        // // 这是个深拷贝的方法
        // function deepClone(obj) {
        //     // if (obj === null) return obj;
        //     // if (obj instanceof Date) return new Date(obj);
        //     // if (obj instanceof RegExp) return new RegExp(obj);
        //     // if (typeof obj !== "object") return obj;
        //     let cloneObj = new obj.constructor();
        //     for (let key in obj) {
        //         if (obj.hasOwnProperty(key)) {
        //             // 实现一个递归拷贝
        //             cloneObj[key] = deepClone(obj[key]);
        //         }
        //     }
        //     return cloneObj;
        // }
        // console.log('obj1', obj1) // obj1 { name: 'xuxu', arr: [ 1, [ 2, 3 ], 4 ] }
        // console.log('obj4', obj4) // obj4 { name: 'gengeng', arr: [ 1, [ 5, 6, 7 ], 4 ] }

2.1 浅拷贝

Object.assign()方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

 // Object.assign(target, ...sources) 
 // 参数  target  目标对象。sources  源对象。
         let obj = {
            name: 'xuxu',
            chi() {
                food: '肉'
            }
        }
        let obj2 = Object.assign({}, obj);
        obj2.name = 'gengegng';
        obj2.chi.food = 'cai';
        console.log(obj);    //{name: "xuxu", chi: ƒ}

3.1深拷贝

这也是利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

let arr = [1, 3, {username: ' kobe'}];
        let arr4 = JSON.parse(JSON.stringify(arr));
        arr4[2].username = 'duncan';
        console.log(arr, arr4)