Javascript中的浅拷贝与深拷贝 | 青训营

81 阅读3分钟

  Javascript中进行对象的复制可以通过深拷贝和浅拷贝两种方式来完成,本文将对深拷贝和浅拷贝区别和使用方法进行学习与总结。

参考链接:《浅拷贝与深拷贝》

1. Javascript中的基本类型和引用类型

  在了解浅拷贝和深拷贝之前需要先掌握Javascript中的基本类型和引用类型的区别。

  在Javascript中,基本数据类型(值类型)的长度是可确定的,因此基本类型的数据被存在栈内存中,基本数据类型包括字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol;

  而引用数据类型的数据长度是不定的,因此引用类型数据存于堆内存中,引用数据类型是object(在Javascrip 中 对象(Object)、数组(Array)、函数(Function)都属于object)。

2. 浅拷贝与深拷贝的区别

  • 浅拷贝

  浅拷贝对对象的复制相当于在堆内存中新建一个对象,对象内属于基本类型的属性字段的属性值会通过开辟新空间的方式拷贝存储,属于引用类型(数组、对象)的属性则是通过拷贝引用地址的方式进行属性复制。 

  当浅拷贝中的引用属性发生变化时,源对象的对应属性也会发生变化(因为属性值共享内存地址),而基本属性则改变则不会影响源对象的对应属性的属性值。

  • 深拷贝

  深拷贝也会在堆内存中新建对象存储复制的数据,但深拷贝会通过循环递归将源对象中的子对象、子数组进行深度拷贝。

  深拷贝的情况下,复制对象的基本属性和引用属性的改变都不会影响源对象的属性变化,因为他们的属性内存是独立分离的。

3. 如何进行浅拷贝与深拷贝

  • 浅拷贝的使用

  实际开发中可以通过原生的Object.assign()、Array.prototype.concat()、Array.prototype.slice()函数进行浅拷贝,也可以通过lodash函数库的clone()方法进行浅拷贝,此外es6 / es2015中还存在一个展开运算符特性可以简单快捷地进行浅拷贝,其功能与Object.assign()相同。

  • 深拷贝的使用

  实际开发中可以通过原生的JSON.parse(JSON.stringify())进行深拷贝、也可以通过lodash函数库的cloneDeep()方法或者是jQuery.extend()方法进行深拷贝,此外也可以自己按照深拷贝的逻辑去写递归代码实现深拷贝。

4. 拓展:

  除了浅拷贝和深拷贝,还有一种类似于对象复制的方式是直接赋值。相较于浅拷贝和深拷贝,将源对象直接赋值给新变量时,所赋的是源对象在栈内的地址而并非堆中的数据。

  在赋值的情形下,对于新变量内部的属性的改变,无论该属性是基本类型还是引用类型都会影响源对象的属性值。

  浅拷贝和深拷贝的学习让我对于对象复制有了更深的理解。之前开发的过程中很少有需要进行对象复制的地方,因此也一直没有注意到这样的问题。这在某种程度上也证实了我对于对象的理解还不够深刻,今后也会在Javascript上多下功夫去学习。