深入解析JS对象的浅拷贝与深拷贝

在js中有5种基本的数据类型:NumberBooleanUndefined、Null、String,还有一种复杂的数据类型––Object,基础数据类型不存在深拷贝和浅拷贝的问题,只有Object对象才会有这个烦恼。

  • 浅拷贝:只是复制一份对象的引用,对象内存地址只有一份,两个引用指向同一个实例地址;
  • var a = {
        name: '小仙女',
        age: '18'
    };
    
    var b = a; // 浅拷贝操作
    
    a.age = 26;
    
    console.info(a.age); // 26
    console.info(b.age); // 26 b也跟着变了
    
  • 深拷贝:把对象内存地址复制一份出来,变成一个新的对象,两个引用指向不同的实例地址。

  • var a = {
        name: '小仙女',
        age: '18'
    };
    
    var b = JSON.parse(JSON.stringify(a)); // 深拷贝操作
    
    a.age = 26;
    
    console.info(a.age); // 26
    console.info(b.age); // 18 b没跟着变
    

     

深拷贝和浅拷贝的深入解析?

浅拷贝:

举个栗子:

var array = new Array();

在这个时候首先执行new Array(),此时浏览器会在内存中开辟一个此数组实例的内存空间,接着执行var array,此时会创建一个array引用,指向new Array()这个实例,进行关联。后面我们就可以通过 array这个引用来访问这个数组,注意:后面都是通过array这个引用来操作数组,如果此时你把array赋值给另一个变量,那么此时这个数组实例就有多个引用同时指向它,而此时把array赋值给另一个变量的操作就是浅拷贝。

例如

var array1 = new Array();
var array2 = array1; // 浅拷贝操作,此时array1、array2都是指向new Array()实例,下同

array1.push(1);
array1.push(2);
array1.push(3);

console.info(array1); // 输出 [1, 2, 3]
console.info(array2); // 输出 [1, 2, 3]

array2 = [];

console.info(array1); // 输出 []
console.info(array2); // 输出 []

深入解析JS对象的浅拷贝与深拷贝_第1张图片

上面的操作中,实例永远只有一份,但同时有2个引用指向它,这个时候2个引用其实操作的永远都是同一个数组。

 

深拷贝:

深拷贝是把原本的对象实例拷贝一份出来变成一个新的实例对象。

举个栗子

var array1 = {
    name: '小仙女',
    age: '18'
};

var array2 = JSON.parse(JSON.stringify(array1)); // 深拷贝操作

深入解析JS对象的浅拷贝与深拷贝_第2张图片

先说说原理:上面说到js的基础数据类型是不存在深拷贝浅拷贝的,因为基础数据类型的值是不可变的,引用和值都是存在栈内存区,这个深拷贝的方法就是利用这一点来实现,首先把a对象转换成基础类型的字符串,然后通过JSON对象方法,把字符串转换成json对象,来实例化一个和a值一样但内存地址不同的对象(注意:这个深拷贝的方法不能拷贝对象中的方法属性

当然还有很多其他实现深拷贝的方法,但在使用的过程中注意每种深拷贝方法的限制,最适合自己的才是最好的。

温馨提示,平时赋值时多注意:使用js操作数组、json对象时,在赋值、传值的时候一定要清楚赋值的目的是什么,想要不影响原本对象,就注意了,此时就要使用深拷贝的方法来进行赋值,而不是直接使用=号进行赋值,不然就是,天正在等烟雨,bug在等你的情景了。

打个比方来说说深、浅拷贝的不同

比如说现在春运的抢票软件,开始你使用携程来抢票,后面你又用360来抢票,但最终都是从12306出票,这种情况你不管换什么抢票软件,最终都要去12306那边下单,这个时候就是浅拷贝,抢票软件就是引用,12306就是对象的内存地址,不管你怎么换抢票软件,12306永远只有一份,你用不同的抢票软件,只是增加了指向12306的引用个数而已,这就是浅拷贝想要深拷贝,就必须增加12306的个数。比如为了分流,单独成立了一个45789的售票系统,并且两边出售的票是一模一样,这个时候你用智行来抢票且智行只从45789下单,这个时候就是深拷贝了,因为智行指向的是45789,携程、360都是指向12306,虽然3个引用的初始值是一样的,但是指向的不是同一个对象,你在智行上抢到了票对携程和360没什么影响,这就是深拷贝。、

总结: 深浅拷贝关键在于等号右边对象的内存地址是不是新的,是则是深拷贝,不是则是浅拷贝。

我现在在项目中比较喜欢使用lodash中的cloneDeep方法,进行对象的深拷贝,附上lodash的链接: Lodash中文文档链接

你可能感兴趣的:(JS技术,js,深拷贝,浅拷贝)