作用域、作用域链
1. 作用域(Scope)
作用域定义了变量和函数的可访问范围。作用域是在函数定义时确定的。JavaScript中的作用域主要分为以下几种:
- 全局作用域:在脚本文件或最外层定义的变量属于全局作用域。全局作用域中的变量可以在代码的任何地方访问。
- 函数作用域:在函数内定义的变量在函数作用域中是局部的,只能在该函数内部访问,函数外无法访问这些变量。
- 块级作用域:使用
let
或const
声明的变量在块级作用域({}
内部)中有效。块级作用域仅在ES6
引入,var
声明的变量没有块级作用域的特性。
var globalVar = "global"; // 全局作用域 function foo() { var localVar = "local"; // 函数作用域 console.log(globalVar); // 可以访问全局变量 console.log(localVar); // 可以访问局部变量 } foo(); console.log(globalVar); // 可以访问全局变量 console.log(localVar); // 报错,无法访问函数内的局部变量
2. 作用域链(Scope Chain)
作用域链是在当前作用域无法找到某个变量时,向外层作用域逐层查找变量的过程,直到找到该变量或到达最外层的全局作用域。如果在全局作用域也未找到,则返回undefined
或抛出ReferenceError
错误。
作用域链从内向外查找,即从当前作用域向全局作用域逐层查找,形成了一个链式结构。
var globalVar = "global"; function outerFunction() { var outerVar = "outer"; function innerFunction() { var innerVar = "inner"; console.log(innerVar); // "inner" - 在当前作用域找到 console.log(outerVar); // "outer" - 在外层作用域找到 console.log(globalVar); // "global" - 在全局作用域找到 } innerFunction(); } outerFunction();
在innerFunction
中:
- 查找
innerVar
时,找到它在当前作用域的定义。 - 查找
outerVar
时,当前作用域没有定义,于是向上一级作用域(outerFunction
)查找,找到了。 - 查找
globalVar
时,内层的作用域都没有找到,最终在全局作用域找到了。
作用域链的构成
作用域链是由嵌套的作用域层次构成的。每个作用域链的链头是当前作用域,逐层往上链接到上级作用域,直到全局作用域。
当执行上下文(如函数调用)被创建时,会形成一个作用域链,使得该执行上下文可以访问各个上层作用域中的变量。