如何实现深拷贝?

时间:2022-10-10 19:57:00

浅拷贝和深拷贝

浅拷贝:拷贝的值为引用而非其真实值 
深拷贝:拷贝的值为真实值而非引用。当拷贝的元素是对象是,深拷贝相当于会重新创建一个对象,并对对象的值一个一个复制过来,而不是仅仅获得该对象的引用值。

为什么要分深浅拷贝

显然,浅拷贝会带来一个很大的问题。就是,如果我复制的值是一个引用地址,那么我通过一个变量去修改这个对象,会导致所有该对象的引用都发生变化。

slice/concat都是浅拷贝

一个例子

var a = [1,2,{name: 'amy'}];
var b = a.concat([]);
b[2].name = 'sam';
console.log(a[2].name);// 输出‘sam’
  • 1
  • 2
  • 3
  • 4

函数参数的按值传递

《javascript高级程序设计》一书有提到函数的参数传递都是按值传递的,但是你会发现你若传入一个引用类型数据并在函数里面修改会导致实参的改变。 
这就是引用类型的奥秘所在。 
js中会为引用类型分配在堆内,而我们声明的变量并不是保存着这个对象,而是保存着对象的引用! 
因此,传入参数时,也是按值传递的。但是,这个值是引用,所以修改同一引用会导致对象的直接变化。

实现深拷贝

那我们如何实现一个深拷贝呢?

function deepClone(obj) {
    var newObj = obj instanceof Array ? [] : {};
    //obj属于基本数据类型,直接返回obj
    if(typeof obj !== 'object') {
        return obj;
    } else {
    //obj属于数组或对象,遍历它们
        for(var i in obj) {
            newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]):obj[i]; 
        }
    }
    return newObj;
}