JS中的堆(Heap)栈(Stack)内存
一、都是在计算机内存中开辟的空间
- 栈内存Stack:ECStack(Execution Context Stack)
- 存储原始值类型值
- 代码执行的环境
- 堆内存:Heap
- 存储对象类型值
二、EC(Execution Context)执行上下文:区分代码执行的环境
- 常见上下文分类:
- 全局上下文EC(G)
- 函数私有上下文EC(?)
- 块级私有上下文EC(Block)
- 函数执行过程:产生私有上下文 -> 进栈执行 -> 出栈释放(可能释放)
- 变量对象:当前上下文中,用来存储声明的变量的地方
- VO(Variable Object):VO(G)或者VO(Block)
- AO(Active Object):AO(?)
三、GO(Global Object)全局对象
- window指向GO对象
- 全局上下文中,基于var/function声明的变量放到GO对象上;而基于let/const声明的变量才是放在VO(G)中的。
四、let 变量 = 值; 的操作步骤
- 第一步:创建值
- 原始值类型:直接储存在栈内存中,按值操作。
- 引用数据类型:按照堆内存地址来操作。
- 对象:开辟一个堆内存空间(16进制地址)、依次存储对象的键值对,把空间地址赋值给变量。
- 函数:内存空间中存储三部分信息
- 作用域[[scope]]:当前所处上下文
- 函数体中的代码字符串
- 当作普通对象存储的静态属性和方法[name & length]
- 第二步:声明变量 declare
- 第三步:变量和值关联在一起(赋值)defined
五、作用域链:<自己私有上下文,作用域(上级上下文)>
- 在私有上下文中遇到一个变量,首先看是否为私有变量(AO)中是否有,如果是私有变量,则接下来操作都是私有的(和外界没有关系)
- 如果不是私有的,则去上级上下文中查找,如果是上级的,则操作都是上级的
- 如果不是上级的,则继续找上级的上级上下文,直到找到EC(G)为止
- 如果EC(G)中也没有
- 如果是获取变量值,会报错
- 如果是设置变量值,则相当于给window设置对应的属性
六、创建、执行函数
- 创建函数
- 开辟堆内存(16进制地址)
- 存储内容
- 作用域:在哪个上下文中创建的,它的作用域就是哪个上下文
- 函数体代码字符串
- 普通对象,存放键值对(静态私有属性方法)
- 把空间地址赋值给变量(或者函数名)即可
- 普通函数执行
- 产生全新的私有执行上下文EC(?),然后进栈执行,在这个私有上下文中生成了一个私有变量对象AO(?)
- 代码执行前:
- 初始化作用域链,明确变量的归属
- 初始化this的指向
- 形参赋值
- 变量提升
- 代码执行
- 出栈释放