返回

JavaScript块级作用域和let的新特性解析

前端

前言

在JavaScript语言中,作用域是指变量的可见范围。在ES2015之前,JavaScript只有两种作用域:全局作用域和函数作用域。全局作用域是整个程序的范围,而函数作用域是指函数内部的范围。在ES2015中,新增了块级作用域,这使得我们可以更精细地控制变量的可见范围。

块级作用域

块级作用域是指代码块内部的范围。代码块可以是花括号包围的语句块,也可以是箭头函数。在块级作用域中声明的变量只能在该块级作用域内使用。

声明变量的作用域

在块级作用域中,变量只能在声明它的代码块内使用。例如,以下代码中,变量x只能在if代码块内使用:

if (true) {
  let x = 10;
}

console.log(x); // ReferenceError: x is not defined

如果我们试图在if代码块外使用变量x,就会报ReferenceError错误。

let变量的暂时性死区

在块级作用域中,let变量在声明之前是不可用的。这被称为暂时性死区(Temporal Dead Zone, TDZ)。例如,以下代码中,变量x在let x = 10;声明之前是不可用的:

console.log(x); // ReferenceError: x is not defined

let x = 10;

如果我们试图在let x = 10;声明之前使用变量x,就会报ReferenceError错误。

for-of循环的块级作用域

在for-of循环中,循环变量的声明具有块级作用域。这意味着,循环变量只能在for-of循环内部使用。例如,以下代码中,变量x只能在for-of循环内部使用:

let numbers = [1, 2, 3];

for (let x of numbers) {
  console.log(x);
}

console.log(x); // ReferenceError: x is not defined

如果我们试图在for-of循环外使用变量x,就会报ReferenceError错误。

块级作用域和闭包

块级作用域和闭包密切相关。闭包是指能够访问另一个函数作用域中的变量的函数。在块级作用域中声明的变量,可以在该块级作用域内的任何地方使用,包括闭包中。例如,以下代码中,变量x可以在闭包函数中使用:

let x = 10;

const fn = () => {
  console.log(x);
};

fn(); // 10

块级作用域和函数提升

在JavaScript中,函数声明会提升到函数所在的块级作用域的顶部。这意味着,函数声明可以在声明之前使用。例如,以下代码是合法的:

foo();

function foo() {
  console.log('Hello, world!');
}

但是,变量声明不会提升。这意味着,变量声明必须在使用之前声明。例如,以下代码是错误的:

console.log(x);

let x = 10;

块级作用域和作用域链

作用域链是指变量在内存中的存储位置。当我们访问一个变量时,JavaScript会沿着作用域链向上查找,直到找到该变量的声明为止。例如,以下代码中,变量x的作用域链如下:

function foo() {
  let x = 10;

  function bar() {
    console.log(x);
  }

  bar();
}

foo();

作用域链:

  • 全局作用域
  • foo函数的作用域
  • bar函数的作用域

当bar函数访问变量x时,JavaScript会沿着作用域链向上查找,直到找到x的声明。