js 作用域
JavaScript 中的作用域定义了变量和函数的可访问性。理解作用域对于编写清晰、可维护的代码非常重要。JavaScript 主要有以下几种类型的作用域:
1. 全局作用域
在全局作用域中声明的变量和函数可以在整个程序中的任何地方被访问。
javascript
var globalVar = "I'm global";
function globalFunction() {
console.log("This is a global function.");
}
console.log(globalVar); // 输出: I'm global
globalFunction(); // 输出: This is a global function.2. 函数作用域
在函数内部声明的变量和函数只能在该函数内部访问。
javascript
function myFunction() {
var funcVar = "I'm local to myFunction";
function innerFunction() {
console.log(funcVar);
}
innerFunction(); // 输出: I'm local to myFunction
}
myFunction();
// console.log(funcVar); // 这里会抛出 ReferenceError: funcVar is not defined3. 块级作用域
使用 let 和 const 声明的变量具有块级作用域,这意味着它们只在声明它们的块(如 { ... })中可见。
javascript
if (true) {
let blockVar = "I'm local to this block";
console.log(blockVar); // 输出: I'm local to this block
}
// console.log(blockVar); // 这里会抛出 ReferenceError: blockVar is not defined
for (let i = 0; i < 5; i++) {
console.log(i); // 输出: 0, 1, 2, 3, 4
}
// console.log(i); // 这里会抛出 ReferenceError: i is not defined4. 模块作用域
在 ES6 模块中,顶级声明的变量和函数默认是模块作用域的,只能在该模块内部访问,除非显式导出。
javascript
// myModule.js
const moduleVar = "I'm local to this module";
function moduleFunction() {
console.log(moduleVar);
}
export { moduleFunction };
// main.js
import { moduleFunction } from "./myModule.js";
moduleFunction(); // 输出: I'm local to this module
// console.log(moduleVar); // 这里会抛出 ReferenceError: moduleVar is not defined[作用域链]
当一个变量被引用时,JavaScript 引擎会在当前作用域中查找该变量。如果找不到,它会沿着作用域链向上查找,直到找到该变量或到达全局作用域。如果最终没有找到,就会抛出 ReferenceError。
javascript
function outer() {
const outerVar = "outer";
function inner() {
const innerVar = "inner";
console.log(outerVar); // 可以访问外部函数的变量
console.log(innerVar); // 可以访问自身作用域的变量
}
inner();
}
outer();[闭包]
闭包是一种特殊的对象,它由函数与其相关的引用环境组合而成。闭包使得函数可以访问其词法作用域内的变量,即使这个函数在其词法作用域之外执行。
javascript
function createCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2在这个例子中,createCounter 返回的匿名函数形成了一个闭包,它保留了对 count 变量的访问权,即使 createCounter 已经执行完毕。