JavaScript 作用域定义了变量或函数在代码中的可访问范围。理解作用域对写出清晰且无错误的代码至关重要。以下是对 JavaScript 作用域的概述:
1. 作用域的分类
JavaScript 中主要有以下几种作用域:
全局作用域:变量或函数可以在代码的任何地方访问。
局部作用域:变量或函数只能在特定的代码块或函数中访问。
此外,还涉及更高级的作用域概念:
函数作用域:函数内声明的变量只能在函数内部访问。
块级作用域:由 {} 包裹的代码块内声明的变量(使用 let 或 const)只能在该块内访问。
词法作用域(静态作用域):变量的作用域在定义时就已经确定。
2. 全局作用域
定义:
全局作用域中的变量可以在整个代码中访问。 使用 var(在全局范围)或直接声明的变量会自动添加到全局对象 window(浏览器环境)或 global(Node.js 环境)中。
示例
var globalVar = "I am global"; // 全局变量
console.log(globalVar); // 输出: I am global
function showGlobal() {
console.log(globalVar); // 输出: I am global
}
showGlobal();
注意:
污染全局作用域:全局变量过多可能会导致命名冲突或难以维护,应该尽量避免。
3. 局部作用域
定义:
局部作用域中的变量只能在特定函数或代码块中访问。
通常通过函数或块级声明(let 和 const)创建。
3.1 函数作用域
函数中用 var 声明的变量属于函数作用域,只能在函数内部访问。
示例
function localScope() {
var localVar = "I am local";
console.log(localVar); // 输出: I am local
}
localScope();
// console.log(localVar); // 报错: localVar is not defined
3.2 块级作用域
使用 let 和 const 声明的变量具有块级作用域,只能在块内部访问。
示例:
{
let blockVar = "I am block-scoped";
const blockConst = "I am also block-scoped";
console.log(blockVar); // 输出: I am block-scoped
}
// console.log(blockVar); // 报错: blockVar is not defined
区别:var vs let vs const
var 没有块级作用域,受函数作用域限制:
if (true) {
var x = 10;
}
console.log(x); // 输出: 10
let 和 const 有块级作用域: javascript 复制代码
if (true) {
let y = 20;
}
console.log(y); // 报错: y is not defined
4. 词法作用域(静态作用域)
JavaScript 使用词法作用域,即作用域在代码定义时就决定,而不是在代码执行时决定。
示例:
function outer() {
let outerVar = "I am from outer";
function inner() {
console.log(outerVar); // 输出: I am from outer
}
inner();
}
outer();
即使 inner() 在 outer() 外部调用,它依然可以访问 outerVar,因为作用域是在定义时绑定的。
作用域与闭包
当内部函数 "记住" 它定义时的作用域时,就形成了闭包。 这使得即使外部函数执行完毕,其内部作用域仍然可以被访问。
示例:
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2