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 引入 let 和 const ,在块 {} 内有效:
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可以创建块级作用域,避免闭包捕获循环变量的问题。