JavaScript 作用链是指在 JavaScript 中查找变量时所遵循的规则和路径。它描述了当前执行上下文及其父级上下文之间的关系。作用链用于解析变量,当在一个作用域中查找变量时,如果当前作用域中没有找到,则会沿着作用链向上查找,直到找到变量或到达全局作用域为止。
作用域(Scope)
-
全局作用域:在代码中的任何地方都可以访问的变量和函数。
-
函数作用域:在函数内部定义的变量和函数,只能在该函数内部访问。
-
块级作用域:通过
let
和const
关键字在块级结构(如if
,for
,while
块)中定义的变量和常量。
作用链的构建
作用链是在函数定义时确定的,而不是在函数调用时。每个函数在创建时都会创建一个包含其自身作用域和所有父级作用域的链。
例子
javascript复制代码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
和 globalVar
。如果 innerFunction
中没有找到某个变量,它会沿着作用链向上查找 outerFunction
和全局作用域。
作用链的查找顺序
-
当前作用域:首先在当前函数的作用域内查找变量。
-
父级作用域:如果在当前作用域内没有找到变量,则沿着作用链向上查找父级函数的作用域。
-
全局作用域:如果在所有父级作用域中都没有找到变量,则在全局作用域中查找变量。
闭包(Closure)
闭包是指函数可以记住并访问其词法作用域,即使函数是在其词法作用域之外执行的。闭包使得函数可以访问外部函数的变量,即使外部函数已经执行完毕。
javascript复制代码function createCounter() { let count = 0; return function() { count++; console.log(count); }; } const counter = createCounter(); counter(); // 1 counter(); // 2 counter(); // 3
在这个例子中,counter
函数形成了一个闭包,它可以访问 createCounter
函数中的 count
变量,即使 createCounter
函数已经执行完毕。
总结
-
作用链:描述了变量查找路径,从当前作用域到父级作用域再到全局作用域。
-
作用域:包括全局作用域、函数作用域和块级作用域。
-
闭包:函数可以记住并访问其词法作用域,即使函数在其词法作用域之外执行。
理解作用链和闭包对于编写复杂的 JavaScript 代码和避免常见的作用域问题非常重要