JS中的堆内存与栈内存

在js引擎中对变量的存储主要有两种位置,堆内存和栈内存javascript

和java中对内存的处理相似,栈内存主要用于存储各类基本类型的变量,包括Boolean、Number、String、Undefined、Null,**以及对象变量的指针,这时候栈内存给人的感受就像一个线性排列的空间,每一个小单元大小基本相等。java

而堆内存主要负责像对象Object这种变量类型的存储,以下图函数

栈内存中的变量通常都是已知大小或者有范围上限的,算做一种简单存储。而堆内存存储的对象类型数据对于大小这方面,通常都是未知的。我的认为,这也是为何null做为一个object类型的变量却存储在栈内存中的缘由。学习

所以当咱们定义一个const对象的时候,咱们说的常量实际上是指针,就是const对象对应的堆内存指向是不变的,可是堆内存中的数据自己的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就至关于const对象的指针,是不可变。指针

既然知道了const在内存中的存储,那么const、let定义的变量不能二次定义的流程也就比较容易猜出来了,每次使用const或者let去初始化一个变量的时候,会首先遍历当前的内存栈,看看有没有重名变量,有的话就返回错误。对象

说到这里,有一个十分很容易忽略的点,以前也是本身一直没有注意的就是,使用new关键字初始化的以后是不存储在栈内存中的。为何呢?new你们都知道,根据构造函数生成新实例,这个时候生成的是对象,而不是基本类型。再看一个例子blog

 

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
console.log(typeof a)
>>> 'object'

  咱们能够看到new一个String,出来的是对象,而直接字面量赋值和工厂模式出来的都是字符串。可是根据咱们上面的分析大小相对固定可预期的即使是对象也能够存储在栈内存的,好比null,为啥这个不是呢?再继续看ip

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

  

很明显,若是a,b是存储在栈内存中的话,二者应该是明显相等的,就像null === null是true同样,但结果二者并不相等,说明二者都是存储在堆内存中的,指针指向不一致。内存

说到这里,再去想想咱们常说的值类型和引用类型其实说的就是栈内存变量和堆内存变量,再想一想值传递和引用传递、深拷贝和浅拷贝,都是围绕堆栈内存展开的,一个是处理值,一个是处理指针。字符串

内存分配和垃圾回收

通常来讲栈内存线性有序存储,容量小,系统分配效率高。而堆内存首先要在堆内存新分配存储区域,以后又要把指针存储到栈内存中,效率相对就要低一些了。
垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量由于存在不少不肯定的引用,只有当全部调用的变量所有销毁以后才能回收。

继续往下思考的话,其中还有不少的东西须要去学习,今天先到这里,后续再来补充。

话说~NaN会不会也是存储在堆内存中的呢?你们想一想吧,欢迎你们来一块儿讨论讨论~文中若有错误欢迎指出~

  --参考木子墨的博客

相关文章
相关标签/搜索