JavaScript中深拷贝与浅拷贝的简介
基础介绍
-
ECMAScript变量包含两种数据类型的值:基本数据类型和引用数据类型。
-
基本数据类型:Boolean、Null、Undefined、Number、String、Symbol(ES6新增),名和值都存在栈内存中。
-
引用数据类型:Object、Array、Function 、Data、RegExp等,名存在栈中,值存在堆中,栈内存会提供一个引用地址指向堆中内存中的值。
-
浅拷贝: 用在引用数据类型赋值后,受原数据影响到赋值操作。也就是说从一个变量给另一个新变量复制引用类型的值,其实复制的就是指针,最终两个变量都指向同一个对象。再通俗的一个例子就是,一个人站在太阳底下,这个人动了,他的影子也动了。
-
深拷贝:用在基本数据类型赋值后,不受原数据影响到赋值操作。也就是说一个变量给另一个新变量复制基本类型的值,是把这个值给了新变量,相当于把这个值去创建一个副本给了新变量。通俗的一个例子就是,路人乙建了一栋别墅,路人甲也去建了一栋一摸一样的,如果他们去装修,两栋别墅各自发生变化,但二者互不影响。
深浅拷贝的实现
深拷贝
let a = 1;
let b = a; // 新开一个空间然后赋值为1,
a = 2
console.log(a); // 2
console.log(b); // 1
复制代码
浅拷贝
- 这个时候无论改变d或者c中的name属性值,二者都将做出相同的变动,因为他们访问的地址是同一个地址。
function foo() {
var a ='甲'
var b = a
var c = {name :'乙'}
var d = c
console.log(d); // {name :'乙'}
}
foo()
复制代码
- null清除了a的指针,也就是栈中a变量值(地址),但是这并不会影响b
let a = {name: "薛之谦"}
let b = a;
a = null
console.log(a); //null
console.log(b); // {name: "薛之谦"}
复制代码
小拓展
JavaScript堆不需要程序代码来显示地释放,因为堆是由自动的垃圾回收来负责的,每种浏览器中的JavaScript解释引擎有不同的自动回收方式
一个最基本的原则是:如果栈中不存在某个对象的引用,那么就认为该对象已经不再需要,在垃圾回收时就会清除该对象占用的内存空间。
因此,在不需要时应该将对象的引用释放掉,以利于垃圾回收,这样就可以提高程序的性能。