作用域与闭包
作用域决定变量在何处可见、可访问;闭包是“函数 + 其创建时的词法环境”的组合,使内层函数能持续访问外层变量。
词法作用域(Lexical scope)
函数定义时书写位置决定它能访问哪些外层变量,而非调用位置。这与 函数 中 this 的绑定规则不同:this 多由调用方式决定,词法作用域由代码结构决定。
var 与「函数作用域」「变量提升」
var:函数作用域,或在全局成为全局对象属性(浏览器模式下)。- 提升(hoisting):声明会被拿到所在作用域顶部“注册”,赋值不提升,故易出现
undefined的暂时表现。 - 现代代码中优先
let/const(见 ES6+)。
块级作用域:let / const
- 块:一对
{}(if、for、独立块等)。 let:可重新赋值;const:绑定不可重新赋值(对象本身仍可变,除非Object.freeze等)。- 不得重复声明同一标识符于同一块内。
暂时性死区(TDZ)
块内 let / const 声明之前的区间,访问该标识符会 ReferenceError。这避免了 var 在块顶“静默 undefined”的部分问题。
闭包(Closure)
function outer(x) {
return function inner(y) {
return x + y // inner「闭合」了 outer 的词法环境中的 x
}
}
const f = outer(1)
f(2) // 3常见用途:工厂函数、防抖节流(见 性能优化)、模块化 模式中的私有状态、事件回调中记住配置等。
注意:闭包会持有对外层变量的引用,配合 DOM 或定时器时若不及时解除引用,可能造成内存无法回收(见 性能优化)。