JS作用域概述、全局、局部作用域

105 阅读3分钟

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

总结

全局作用域:变量在程序的任何地方都可访问。

局部作用域:

函数作用域:通过函数定义的作用域。

块级作用域:由 let 和 const 创建的块范围变量。

词法作用域:作用域在代码定义时就已经决定。

尽量减少全局变量,推荐使用块级作用域来编写安全、易维护的代码。