作用域和堆栈内存
今天来详细解释一下作用域和变量提升,因为最近的课程也讲到了,我认为有必要把这块在拓展一下
基于let, const ,class, import等ES6中的等方式创建变量,不存在变量提升
后期函数中代码执行,遇到一个变量,首先看是否为自己上下文中私有变量,如果以后操作的都是自己的私有变量,和外界无关;如果不是自己私有的,则按照作用域链,到上一级上下文EC(G)中查找,看看是否是它的...我们把变量的这种查找机制,叫做“作用域链”,一直找到全局上下文位置
代码执行前的预处理:
1、初始化作用域链:scope-chain(EC(FN1), EC(G))
2、初始化this
3、形参赋值
5、变量提升
6、代码开始执行
一般函数执行,形成的上下文,在函数执行完都会出栈释放,以此保证内存优化,;如果当前上下文中的某些东西,被上下文之外的变量等占用了,则不能出栈释放,此上下文之前存储的私有变量也都保存下来了
作用域链和函数在哪执行没关系,上级作用域[[scope-chain]],只和在哪创建的有关系,创建时候就已经决定了未来作用域链的指向
在JS非严格模式下,arguments和形参变量存在映射机制(因为都是用来存储传递的实参信息的,arguments不管是否定义形参都会存在,定义形参后,不仅形参可以获取传递的值,arguments中也存储了传递的值,此时两者有映射机制)
第一个形参变量 映射 arguments[0]
第二个形参变量 映射 arguments[1]
后期不论是形参变量更改值,还是arguments更改每一项的值,互相都会跟着改变
"use strict"; //使用JS严格模式,映射机制不存在,此处只是把arguments修改了,形参是不会跟着改变的
自执行函数的创建和执行发生在代码执行阶段
堆栈释放问题:
JS中的内存:堆内存(HEAP)和栈内存(STACK)
堆内存是用来存储引用数据类型值的(例如:创建函数的创建对象,就是开辟一个堆内存,把代码字符串或者键值对存储到堆内存中)
栈内存是用来执行代码和存储基本类型值的(创建变量也存在里面了),而且不仅全局代码执行(EC(G)全局执行上下文),而且函数执行(EC(X)私有上下文),最后也都会进栈执行的
x=y={xx:"xx"}
1、先创建堆
2、x={xx:"xx"}
3、y={xx:"xx"}
浏览器常用的垃圾回收机制(内存释放机制):
查找引用(webkit内核):
浏览器有自动回收垃圾的机制,定期间隔某段时间,把所有没有被占用的内存回收释放
创建一个堆(16进制地址),如果有变量或者其他东西存储了堆内存地址,则当前堆内存被视为占用,也就不能释放销毁
上下文进栈执行,如果当前上下文中的某些内容(一般也是当前上下文中创建的堆)被上下文以为的变量或者其他事务所占用,那么当前上下文就不能出栈释放(一般情况下,上下文中代码执行完,上下文自己就出栈释放了)
内存计数器方式(Trident内核):
当前内存被其他东西引用了,则给堆计数+1(累加计数),取消占用后,则-1,当减到零之后,浏览器就可以把它释放了
如果堆内存用完后,手动释放它,则取消所用的占用:赋值为null(null是空对象指针,也就是不指向任何的堆内存)
- 点赞
- 收藏
- 关注作者
评论(0)