首先执行上下文的概念,执行上下文是评估和执行Js代码运行环境的抽象概念,任何Js代码在执行时,都是在对应的上下文中执行。
执行上下文有三种类型,全局上下文,函数上下文以及Eval上下文。
全局上下文:最外层或最顶层的上下文,仅同时存在一个全局上下文,在浏览器运行环境下,执行上下文的this指向为window
函数上下文:函数上下文在函数调用时被创建,同一函数可以创建多个执行上下文
Eval上下文:实际运用中较少见,不加讨论
执行上下文的创建和消费都是经过js引擎,代码预加载及执行时可能存在多个执行上下文,因此,执行上下文调用堆栈用于记录这些执行上下文,调用堆栈是一个先进后出的栈结构,在创建时,Js引擎会先创建全局执行上下文并将其入栈,之后如果遇到代码中的函数调用,则创建对应的函数上下文并将其入栈,预扫描完毕后,栈顶执行上下文中的JS代码将被执行,然后该执行上下文出栈,若栈未空则重复上述步骤直至函数上下文及全局上下文中的JS代码执行完毕,因此,全局上下文每次都是最先创建,最后执行完毕。
执行上下文的创建分为两个阶段:创建阶段、执行阶段
创建阶段主要内容有:
- 确定This绑定
- 创建词法环境组件
- 创建变量环境组件
如此前所说,浏览器中全局上下文的This指向为window,函数执行上下文由调用对象决定,如果没有则为undifined,严格模式下会报错。
词法环境组件跟变量环境组件相似,只是词法环境组件中包含了变量及其引用的绑定关系。
词法环境组件包含三部分:
- This指向绑定
- 自身环境记录器(若为全局上下文,该项为对象环境记录器,包含了浏览器提供的属性及方法引用;若为函数上下文,该项为声明式环境记录器,包含函数声明及变量)
- 对外层环境的引用(如果为全局上下文,该项为null)
创建阶段执行上下文为所需变量分配存储空间,执行阶段会录入对象的引用值,包括原始类型,对象的引用等。
红宝书中提到的,每一个执行上下文都会绑定一个变量对象,其实指的就是词法环境组件
作用域决定了上下文中能够访问哪些变量,如果一个变量在当前上下文中找不到值,会向外层作用域继续寻找,直到最外层的引用指向为null,该实现基于环境记录器中包含了对外层环境记录器的引用。
JS中的词法作用域是静态词法作用域,变量的值在定义时已经决定了,闭包的含义可以简单总结为一个对象引用了外层作用域的变量,由于JS中的变量存储在堆栈中,当出现闭包时,该对象会挟持该变量,表现为记录该变量的引用,因为调用堆栈每次调用只执行栈顶代码,不记录该引用的话,执行时获取不到外层数据。同样的,由于这种“挟持”的存在,被引用的对象不会被JS内存机制回收,容易造成内存泄漏。
标签:闭包,执行,变量,作用域,创建,词法,上下文 From: https://www.cnblogs.com/LinPQ/p/16714220.html