小白学 VUE 系列JS的深浅拷贝:数组,对象深浅拷贝

出现原因

出现深浅拷贝的问题,实质上是由于JS对基本类型和引用类型的处理不同。基本类型指的是简单的数据段,而引用类型指的是一个对象,而JS不允许我们直接操作内存中的地址,也就是不能操作对象的内存空间,所以对对象的操作都只是在操作它的引用而已。
如果我们复制一个基本类型的值时,会创建一个新值,并把它保存在新的变量的位置上。
而如果我们复制一个引用类型时,同样会把变量中的值复制一份放到新的变量空间里,但此时复制的东西并不是对象本身,而是指向该对象的指针。所以我们复制引用类型后,两个变量其实指向同一个对象,改变其中一个对象,会影响到另外一个。

js 数据类型

  • 基本类型(单类型):除Object。 String、Number、boolean、null、undefined。
  • 引用类型:object。里面包含的 function、Array、Date

我们操作基本类型的时候,拷贝和复制都不会出现引用问题

var a=10;
var b=a;
b=15;
console.log(a,b);//10,15,

这个a变量并没有被改变,因为它是基本类型

var arr=[
    {name:"a"},
    {name:"b"}
];
var arr2=arr;
arr[0].name="a-update";
console.log(arr,arr2);

黑白课堂
这个时候就出现了浅拷贝的现象,我们并不想 arr2 也被修改了。因为我们复制的只是引用地址
黑白课堂

内部实现了浅拷贝

  • Object.assign() 实现
  • slice()方法
var arr1 = ['red','green'];
var arr2 = arr1.slice(0);//复制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改变color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]

看起来像是深拷贝,其实slice方法只适用于一维数组的拷贝,在二维数组中就会破绽百出

  • concat
var arr1 = ['red','green'];
var arr2 = arr1.concat();//复制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改变color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]

看起来像是深拷贝,其实concat方法只适用于一维数组的拷贝,在二维数组中就会破绽百出

深拷贝方法

  • JSON.parse
var arr1 = ['red','green'];
var arr2 = JSON.parse(JSON.stringify(arr1));//复制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改变color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]
  • 自定义方法
function deepClone(obj){
    //判断参数是不是一个对象
    let objClone = obj instanceof Object?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    

总结

  • 1:深拷贝只是从源数据中拷贝一份出来进行操作,而不是改变源数据;改变源数据的那是浅拷贝;
  • 2:原生js方法slice、concat都不是真正意义上的深拷贝,都仅只适用于一维数组,拷贝的属性不够彻底;
  • 3:实现js深拷贝我们可以通过JSON.parse(JSON.stringify())、递归以及JQuery库的extend方法来实现;

评论区 (0)

没有记录
支持 markdown,图片截图粘贴拖拽都可以自动上传。
黑白课堂

黑白课堂 · 技术专家

专业PHP开发

年度VIP 站长创业者玉树凌风每天醒来0收入
查看更多

最新视频课程