JS中的栈内存和堆内存

788 阅读2分钟

Q:const声明的是常量,只读,那const的值能修改吗?
A:const保存的是指向数组或对象的指针。 const定义的是基本数据类型则不能改变,若定义的是引用数据类型,则可以通过修改对象属性等方法来改变。

栈内存和堆内存

栈内存:存储 String , NUmber , Boolean , Null , Undefined , Symbol等内存有限的基本数据类型,栈内存线性有序存储,容量小,系统分配效率高
堆内存:存储 Object 这种引用数据类型(除基本数据类型之外),其内存大小未知,堆内存首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些。

因此当我们定义一个const对象的时候,我们说的常量其实是指针,就是const对象对应的堆内存指向是不变的,但是堆内存中的数据本身的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就相当于const对象的指针,是不可变。

注: new关键字初始化的存储是在堆内存中的,因为根据构造函数生成的实例是一个对象

var a = new String('123')
var b = String('123')
var c = '123'
console.log(a==b, a===b, b==c, b===c, a==c, a===c)  
>>> true false true true true false

浅拷贝和深拷贝

浅拷贝,复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化。
以下例子,b只是复制了a的指针地址(栈内存中的值),a与b都同时指向同一个对象,所以修改数组a,数组b也跟着变了。

let a = [0,1,2,3,4]
let b = a
console.log( a === b )
a[0] = 1
console.log(a,b)
-------------------------------
结果:
true
[1,1,2,3,4]  [1,1,2,3,4]

深拷贝,将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变。

function deepClone (obj) {
    let _obj = JSON.stringify(obj)
    let objClone = JSON.parse(_obj)
    return objClone
}    
let a = [0,1,[2,3],4]
let b = deepClone(a)
a[0] = 1
a[2][0] = 1
console.log(a,b)
-----------------------------
结果:
[1,1,[1,3],4]  [0,1,[2,3],4]

es6中的Object.assign()第一级属性深拷贝,以后级别属性浅拷贝

垃圾回收

垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收