前端的浅拷贝和深拷贝

一、什么是浅拷贝、什么是深拷贝

 最近自己面试被问到浅拷贝、深拷贝,关键是自己一时回答不上了,所以恶补一下。

我们都知道js的数据类型分为基本类型和引用类型,一般讨论到浅拷贝和深拷贝的都是针对引用类型的,像Object和Array这样的复杂类型

1、浅拷贝:以Object为例

var  a  =  {
    name:  'liner'
};

var  b  =  a;
b.name  =  'Jiejie';
console.log(b.name);    // Jiejie
console.log(a.name);    // Jiejie

  可以看出,对于Object类型,当我们将a赋值给b,然后更改b中的属性,a也会随着变化。
  也就是说a和b指向了同一块内存,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝。

2、深拷贝

我们如果给b放到新的内存中,将a的各个属性都复制到新内存里,就是深拷贝。
也就是说,当b中的属性有变化的时候,a内的属性不会发生变化。

二、浅拷贝的实现

1、Object.assign()

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 

var  target  =  {a:  1,  b:  1};
var  obj1  =  {a:  2,  b:  2,  c: {ca:1}};
var  obj2  =  {c:  {ca:  3,  cb:  2,  cd:  1}};
var  result  =  Object.assign(target,  obj1,  obj2);

console.log(target);    // {a: 2, b: 2, c: {ca: 3, cb: 2, cd: 1}}
console.log(target  ===  result);    // true
可以看到,Object.assign()拷贝的只是属性值,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。所以Object.assign()只能用于浅拷贝或是合并对象。这是Object.assign()值得注意的地方。

 



三、深拷贝的实现

1、层级拷贝,用递归实现。

    function deepClone(obj){
        //定义对象来判断当前的参数是数组还是对象
        let objClone = Array.isArray(obj)?[]:{};
        //如果obj存在并且为对象        
        if(obj&&typeof obj == "object"){
            for(let key in obj){
                if(obj.hasOwnProperty(key)){
                    //如果obj的子元素为对象,那么递归(层级遍历)
                    if(obj[key]&&typeof obj[key] == "object"){
                        objClone[key] = deepClone(obj[key]);
                    }else{
                    //如果不是,直接赋值
                        objClone[key] = obj[key];
                    }
                }
            }
        }    
        return objClone;
    }

2、JSON解析(底层原理也是层级遍历)

var a =  [0,1,2,[3,4],5];
var b = JSON.parse(JSON.stringify(a));
console.log(b); //[0,1,2,[3,4],5];
console.log(a  ===  b);    // false

 b就是拷贝的结果,修改b不影响a。但是这种方法也有缺陷:

  1. 无法复制函数
  2. 原型链没了,对象就是object,所属的类没了。
原文地址:https://www.cnblogs.com/aixue/p/13236471.html