一、堆栈
1、内存构成、作用域(链)与this
JS的内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。
栈
1、栈是一个数组结构的连续的内存空间,是描述方法执行的内存模型。
2、每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)。
3、栈的存储特性遵循“先进后出,后进先出”的LIFO结构。
4、每个线程对应一个栈,用来存放该线程执行方法的信息(实际参数、局部变量等)。
5、属于线程私有,不能实现线程间的共享。
6、栈是由系统自动分配,速度快。
7、方法执行完毕,对应的栈帧被立即弹出栈并释放。
堆
1、堆是一个树形结构的数组,一般用来存储比较复杂的数据对象。
2、内存中只有一个堆,被所有线程共享。
3、堆是一个不连续的内存空间,分配灵活,速度慢。
4、堆划分为代码区(code space)、map区(map space)、大对象区(large object space)、新生代(new space)、老生代(old space)等等。
PS: 需要注意的是闭包中的基本数据类型变量不保存在栈内存中,而是保存在堆内存中。
池
池存放常量,所以也叫常量池。
2、运行时内存
js引擎在读取js代码时会进行两个步骤:
第一步是解释(通篇扫描所有的js代码,然后把当前函数内的所有声明提升到顶端);
第二步是执行。
在一个函数被执行的时候,会进行如下操作:
1、创建执行上下文(this)的内部对象,一般指向函数的拥有者,由当前运行环境而定;
2、获取特殊变量arguments,表示传入值;
3、在函数体内创建当前函数的作用域,并解释函数体内的代码,并把基本数据类型(string、boolean、number、null、undefined)、引用数据类型(变量)、程序运行状态、方法返回值等保存在当前作用域;
4、创建变量对象的一个作用域链,并以数组的形式绑定在函数的[[scopes]]属性(可以通过打印func.prototype看到)上,优先级依次降低,保证对执行环境有权访问的所有变量和函数的有序访问;
5、创建一个栈帧,并放入栈顶,开始执行;
PS:
1,引用数据类型(变量)会在堆内存中创建对象,并以0x00000001标记给当前对象。
2,[[scopes]]在浏览器中最后一项Global指向window,还有Block表示块级作用域,Closure表示闭包,Script等。
3,变量的生命周期包含了声,、初始化与赋值三个过程。
堆和栈的区别:
1、栈的内存管理是顺序分配的,而且有最大长度限制,不存在内存回收问题;而堆则是随机分配内存,不定长度,存在内存分配和垃圾回收的问题;
2、栈代表了处理逻辑,解决程序的运行问题,即程序如何执行,或者说如何处理数据;而堆代表了数据,解决的是复杂数据存储的问题。
3、堆与栈的分离,使得堆中的内容可以被多个栈共享。
4、栈和堆的拆分,使得动态增长成为可能,相应栈中只需记录堆中的一个地址即可,提高了栈的运行效率。
2、闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包的常见方式,就是在一个函数内部创建另一个函数。
闭包存在的
(未完,还在总结)
参考资料:
1
网友评论