JavaScript作用域链
JavaScript作用域链
编程语言中的作用域可分为:
词法作用域:大多数
动态作用域
JS 中只支持词法作用域, this 机制某种程度上很像动态作用域。
词法域所见即所得,易于理解。
闭包是基于词法域书写代码时产生的自然结果。
词法作用域
书写位置决定作用域。
欺骗词法:在运行时修改作用域。
eval:运行时植入JS代码。
with:运行时指定作用域。
闭包是基于词法作用域
作用域(scope)
作用域指的是 变量 的作用域。作用是隔离变量,限制一个变量的影响范围。
变量的作用域是在定义时就确定的,对代码进行静态分析就可以确定。
词法作用域:定义在词法阶段的作用域,也叫做静态作用域。
动态作用域:不关心定义,只关心调用,运行时确定,作用域链基于调用栈。
ES5 作用域:
- 全局作用域
- 函数作用域:function
- 块级作用域
全局作用域
在全局声明
未声明直接使用
函数作用域
在函数内部声明的变量
块级作用域
隐形块级作用域
with
catch 子句
ES6 开始正式支持:
let
const
作用域链(Scope Chain)
在 JavaScript 中,函数也是对象,它的 [[Scope]] 内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链。
内部属性仅供 JavaScript 引擎访问
作用域链决定了哪些数据能被函数访问。
一般来说,函数的作用域链至少包括其本身作用域和全局作用域。
函数与函数的嵌套形成了作用域链
作用域链的本质上是一个指向“变量对象”的指针列表。
作用域链的第一个对象始终都是当前执行上下文的变量对象,全局执行上下文的变量对象始终是作用域链的最后一个对象。
变量提升和函数提升
在作用域中 var变量 和 函数 的声明会被提升到作用域的开头。
并且,当函数名和 var 变量名相同时,函数名会覆盖变量名。
函数表达式不会提升。
变量查询机制
左查询(LHS):查询变量的内存地址。如果在作用域链上查询不到,默认情况下就会创建一个全局变量,严格模式下则会抛出 ReferenceError 异常。
右查询(RHS):查询变量的值。在作用域链上查询不到则会抛出 ReferenceError 异常。

