JavaScript-深浅拷贝

我们知道,JavaScript的数据类型分为基本数据类型和引用型数据类型。

对于基本数据类型而言,并没有深浅拷贝的区别,这里所说的深浅拷贝是针对引用型数据类型的。

浅拷贝:

只是简单的复制(赋值),不会开辟新栈,复制的结果是两个对象都指向同一个地址,修改任意一个对象的属性,另外一个对象的属性也跟着该改变。

```
    const = originArray = [1,2,3,4,5];
    const = originObj = {a:'a',b:'b',c:[1,2,3]};
    
    const cloneArray = originArray;
    const cloneObj = originObj;
    
    console.log(cloneArray);    //[1,2,3,4,5]
    console.log(originObj); //{a:'a',b:'b',c:Array[3]}
    
    cloneArray.push(6);
    cloneObj.a = {aa:'aa'};
    
    console.log(cloneArray);    //[1,2,3,4,5,6]
    console.log(originArray);   //[1,2,3,4,5,6]

    console.log(cloneObj);  //{a:{aa:'aa'},b:'b',c:Array[3]}
    console.log(originObj); //{a:{aa:'aa'},b:'b',c"Array[3]} 
```   

深拷贝:

开辟新栈,两个对象对应两个不同的地址,改变其中一个对象的属性,另外一个对象的属性不发生改变。

深拷贝的实现方法:

1、利用JSON对象中的parse和stringfy
2、利用递归来实现每一层都重新创建对象并赋值

JSON.stringfy();将一个JavaScript值转为一个JSON字符串
JSON.parse();是将一个JSON字符串转成一个JavaScript值或对象
第一种方法实现:
    const originArray = [1,2,3,4,5];
    const cloneArray = JSON.parse(JSON.stringfy(originArray));
    console.log(cloneArray === originArray);//false
    
    const originObj = {a:'a',b:'b',c:[1,2,3]};
    const cloneObj = JSON.parse(JSON.stringfy(originObj));
    console.log(cloneObj === originObj);//false
    
    cloneObj.a = 'aa';
    cloneObj.c = [1,1,1];
    
    console.log(cloneObj);  //{a:'a',b:'b',c:[1,1,1]}
    console.log(originObj); //{a:'a',b:'b',c:[1,2,3]}
    
    但是这种方法并不完善,undefined、function、symbol会在转换过程中被忽略。
    
    如果对象中有函数时,就不能用这个方法进行深拷贝。
 
 第二种方法实现:
    function deepClone(source){
        const targetObj = source.constructor === Array ? []:{}; //判断复制的目标是对象还是数组
        for(let keys in source){
            if(source.hasOwnProperty(keys)){
                if(source[keys] && typeof source[keys] === 'object'){   //如果值是对象,就递归一下
                    targetObj[keys] = source[keys].constructor === Array?[]:{};
                    targetObj[keys] = deepClone(source[keys]);
                
                }else{  //如果不是,就直接赋值
                    targetObj[keys] = source[keys];
                }
            }
        }
        return targetObj;
    }
    
    const originObj = {
        name:'xiaochaochao',
        say:function(){
            console.log('hello world');
        }
    }
    console.log(originObj); //{name:'xiaochaochao',say:f}
    const cloneObj = deepClone(originObj);
    console.log(cloneObj);//{name:'xiaochaochao',say:f}

JavaScript中的拷贝(都是 浅拷贝):

concat();   slice();
es6新增的obj.assign(); ...(扩展运算符)

总结:

1、赋值运算符进行的是浅拷贝
2、JavaScript中的四种方法看起来是深拷贝,但其实是浅拷贝
3、JSON.stringfy是深拷贝
4、递归可以实现全部的深拷贝


阅读 101

推荐阅读