跳到主要内容

JS 函数作用域与闭包

函数作用域与闭包是 JS 高级特性核心,理解它们有助于写出安全、模块化、状态可控的代码

函数作用域(Function Scope)

JavaScript 中,作用域决定了变量的可访问范围。主要有 全局作用域函数作用域(局部作用域)。

js
let globalVar = "全局变量";

function testScope() {
let localVar = "局部变量";
console.log(globalVar); // 可访问全局变量
console.log(localVar); // 可访问局部变量
}

testScope();
console.log(globalVar); // 可访问
// console.log(localVar); // 报错:localVar 在函数外不可访问
  • 函数内部定义的变量只在函数内部有效。
  • 外部变量可以在函数内部访问。

块级作用域(Block Scope)

ES 6 引入 letconst ,在块 {} 内有效:

js
{
let x = 10;
const y = 20;
console.log(x, y); // 10 20
}
// console.log(x, y); // 报错
  • var 只有函数作用域,没有块级作用域。

闭包(Closure)

闭包是指 函数可以访问定义在外部函数中的变量,即使外部函数已经执行完

js
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}

const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
  • inner 是闭包,访问了 outer 的变量 count

  • 外部函数执行完毕后, count 仍然被保存在内存中。

  • 闭包常用于:

    • 数据封装(私有变量)
    • 函数工厂
    • 回调函数保持状态

闭包注意事项

  • 不要滥用闭包,容易造成内存泄漏。
  • 在循环中创建闭包时要注意作用域:
js
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 3 3 3
}, 100);
}

for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 0 1 2
}, 100);
}
  • 使用 let 可以创建块级作用域,避免闭包捕获循环变量的问题。