执行上下文,作用域和垃圾清理
本文最后更新于:2023年1月12日 下午
执行上下文,作用域和垃圾回收
执行上下文是当前JavaScript
代码被解析和执行时所在环境的抽象概念。变量或函数的上下文决定了它们可以访问哪些数据。
执行上下文的类型
执行上下文包含全局执行上下文、函数执行上下文和eval
执行上下文(不建议使用)
全局执行上下文:是最外层的上下文,在浏览器环境中就是全局对象window
,this
指向这个全局对象。全局执行上下文仅此一个
函数执行上下文:当函数被调用时,会创建一个函数执行上下文并推到一个上下文栈,等到函数执行完,上下文栈会弹出该函数执行上下文。可以存在无数个,且每次调用创建的是一个新的执行上下文
eval
函数执行上下文:指的是运行在eval
函数中的代码
所有通过
var
定义的全局变量和函数都会成为window
对象的属性和方法。使用let
和const
的顶级声明不会定义在全局上下文中上下文在其所有代码都执行完毕后会被销毁
执行栈也叫调用栈,具有LIFO
(后进先出)结构,用于存储在代码执行期间创建的执行上下文
1 |
|
作用域
当执行上下文中的代码在执行的时候,会创建变量对象的一个作用域链。这个作用域链决定了各级上下文所能访问到的变量和函数顺序。处在作用域顶端的执行上下文,叫做活动对象。活动对象最初只用arguments
。作用域链的中的下一个变量对象来自于包含上下文,再下一个来自于在下一个包含上下文。全局执行上下文的变量对象始终是作用域链的最后一个变量对象。
垃圾回收
垃圾回收有两种策略,标记清除法和引用计数法。现阶段浏览器使用的多为标记清楚法。
引用计数无法清除循环引用。
1 |
|
内存泄漏
- 缺少声明关键字导致的内存泄漏
1 |
|
当调用test()
时,会在全局对象window
上添加name
属性导致内存泄漏,只要window
不被清理就不会消失
- 定时器导致的内存泄漏
1 |
|
定时器的回调通过闭包引用了外部变量。只要定时器一直运行,回调函数中引用的name
就会一直占用内存
- 使用
JavaScript
闭包造成的内存泄漏
1 |
|
调用outer()
会导致分配给name
的内存被泄漏