欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深拷贝与浅拷贝的区别以及实现方式介绍

程序员文章站 2022-07-07 23:48:27
头两天面试遇到拷贝方面的问题,不过当时并没有给面试官一个满意的回答。所以,今天我们来深入探索一下深浅拷贝。 在说深浅拷贝之前,我们先来聊聊JavaScript变量的基本类型(un...

头两天面试遇到拷贝方面的问题,不过当时并没有给面试官一个满意的回答。所以,今天我们来深入探索一下深浅拷贝。

在说深浅拷贝之前,我们先来聊聊JavaScript变量的基本类型(undefined,boolean,number,string,null)与引用类型(Array,Object)。基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象。

基本类型

基本类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们是通过按值来访问的。 引用类型

引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。 这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。(这是别的哥们总结的,非常棒!我直接把原话拿过来了。)

由此可得出:基本类型的比较是值的比较,只有在它们的值相等的时候它们才相等。引用类型的比较是引用的比较,只有引用地址和值同时相等的时候它们才相等。同时它们之间一个最大的区别在于:基本类型是按值传递,引用类型是按引用传递。这里需要注意的是:深浅拷贝只适用于array与object。

浅拷贝只复制指向某个对象的引用地址,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

这样说可能显得很抽象,我们举例说明:

浅拷贝实现

方法一:赋值运算符

var a = [1, 2, 3],
    b = a
console.log(a) //[1, 2, 3]
console.log(b) //[1, 2, 3]
b[0] = 99;
console.log(a) //[99, 2, 3]
console.log(b) //[99, 2, 3]

方法二:for in 循环

var obj = {a: 1,arr: [2, 3]};
        var shallowObj = shallowCopy(obj);
        function shallowCopy(src) {
            var copyObj = {};
            for (var i in src) {
                if (src.hasOwnProperty(i)) {
                    copyObj[i] = src[i];
                }
            }
            return copyObj;
        }
        console.log(obj);  //{a: 1,arr: [2222, 3]}
        shallowObj.arr[0] = 2222;
        console.log(shallowObj);  //{a: 1,arr: [2222, 3]}

从上面的实现代码不难看出!浅拷贝只是引用地址的拷贝,不管更改任何一方都会影响到另一方,因为它们根本就是同一个对象。

深拷贝实现

方法一:递归拷贝

var mySelf = {name: '猫哆哩',hobby: ['敲代码', '玩游戏', '打台球']};
        function deepCopy(p, c) {    
            var c = c || {};    
            for (var i in p) {      
                if (typeof p[i] === 'object') {        
                    c[i] = (p[i].constructor === Array) ? [] : {};        
                    deepCopy(p[i], c[i]);      
                } else {         
                    c[i] = p[i];      
                }    
            }    
            return c;  
        }  
        var Doctor = deepCopy(mySelf);
        Doctor.hobby.push('听音乐');
        console.log(mySelf);  //{name: '猫哆哩',hobby: ['敲代码', '玩游戏', '打台球']};
        console.log(Doctor);  //{name: '猫哆哩',hobby: ['敲代码', '玩游戏', '打台球', '听音乐']};

所谓”深拷贝”,就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用”浅拷贝”就行了。

方法二:jquery的$.extend()

jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象。

深拷贝与浅拷贝的区别以及实现方式介绍

这里需要特别强调一下 deep 参数,简单的说deep为true就是深拷贝,为false就是浅拷贝。

当然,还有很多方法可以实现深浅拷贝。在这里就不多废话了!重点是我TM更博的速度确实慢,这也是自身能力不足,不知道写什么好。总之,任重道远、贵在坚持吧。