Logo
Section 1 / 32

var、let 和 const 以及暂时性死区

学习 ES6 中引入的声明变量的新方式。

导入

var、let 和 const 以及暂时性死区

学习 ES6 中引入的声明变量的新方式。

随着 ES6 中引入 let 和 const,我们可以根据需求更准确地定义变量。在之前的 JavaScript 入门内容中,我们已经了解了这三种关键字的基本区别,现在我们将深入探讨。

var

使用 var 关键字声明的变量是 函数作用域 的,这意味着即使我们在 for 循环(属于块级作用域)内部声明变量,它们在循环外部依然可以访问。

1for (var i = 0; i < 10; i++) { 2 var leak = "我在循环外部也可见"; 3} 4 5console.log(leak); 6// 我在循环外部也可见

下面我们看一个函数作用域变量的例子:

1function myFunc(){ 2 var functionScoped = "我只在这个函数内部可用"; 3 console.log(functionScoped); 4} 5myFunc(); 6// 我只在这个函数内部可用 7console.log(functionScoped); 8// ReferenceError: functionScoped 未定义

在第一个例子中,var 声明的变量“泄漏”出了块级作用域,可以在外部访问;而在第二个例子中,var 被限制在函数作用域内,无法从外部访问。

let

使用 let(以及 const)关键字声明的变量是 块级作用域 的,这意味着它们仅在声明所在的块及其子块中有效。

1// 使用 `let` 2let x = "global"; 3 4if (x === "global") { 5 let x = "块级作用域"; 6 console.log(x); 7 // 预期输出:块级作用域 8} 9 10console.log(x); 11// 预期输出:global

下面是使用 var 的相同示例:

1// 使用 `var` 2var y = "global"; 3 4if (y === "global") { 5 var y = "块级作用域"; 6 console.log(y); 7 // 预期输出:块级作用域 8} 9 10console.log(y); 11// 预期输出:块级作用域

如你所见,当我们在块级作用域中用 let 重新赋值时,外层作用域的变量并未改变;而使用 var 时,变量值被修改并“泄漏”到了外层作用域。

const

与 let 类似,const 声明的变量也是 块级作用域 的,但不同之处在于,其值 不能通过重新赋值更改,也不能重新声明。

1const constant = '我是一个常量'; 2constant = "我不能被重新赋值"; 3 4// Uncaught TypeError: Assignment to constant variable

重要: 这并不意味着用 const 声明的变量是不可变的。

const 声明的对象内容

1const person = { 2 name: 'Alberto', 3 age: 25, 4} 5 6person.age = 26; 7console.log(person.age); 8// 26

在此情况下,我们并没有重新赋值整个变量,而是修改了对象的一个属性,这是允许的。


注意:我们仍然可以冻结 const 对象,使其内容无法被更改(尽管尝试修改对象属性时不会抛出错误)。

1const person = { 2 name: 'Alberto', 3 age: 25, 4} 5 6person.age = 26; 7console.log(person.age); 8// 26 9 10Object.freeze(person); 11 12person.age = 30; 13 14console.log(person.age); 15// 26

暂时性死区

接下来我们来了解一个非常重要的概念——虽然名字听起来复杂,但实际上并不难理解。

先看一个简单例子:

1console.log(i); 2var i = "我是一个变量"; 3 4// 预期输出:undefined
1console.log(j); 2let j = "我是一个 let 变量"; 3 4// 预期输出:ReferenceError: 无法在初始化前访问词法声明 `j`

var 变量可以在声明之前访问,但此时值为 undefined;而 let 和 const 变量在声明之前是无法访问的。

尽管有些资料说法不同,但事实上 var、let 和 const 都会经历 提升(hoisting) —— 即在代码执行前就被处理,并被提升到其作用域的顶部(无论是全局还是块级作用域)。

主要区别在于:var 在声明前仍可访问,值为 undefined;而 let 会让变量处于一个 暂时性死区,直到声明语句执行为止。如果在声明前访问,就会抛出错误,这有助于更清晰地发现潜在问题,而不是得到一个意外的 undefined。


何时使用 var、let 和 const

没有硬性规定必须在何处使用哪一个,不同开发者也有不同看法。以下是两位知名 JavaScript 开发者的观点。

第一种观点来自 Mathias Bynens:

  • 默认使用 const
  • 仅在需要重新绑定时才使用 let
  • ES6 中应完全避免使用 var

第二种观点来自 Kyle Simpson:

  • 对于跨多个(尤其是较大范围)作用域共享的顶层变量,使用 var
  • 对于较小作用域中的局部变量,使用 let
  • 在编写部分代码后,若确定无需重新赋值,再将 let 改为 const

选择哪种方式完全取决于你自己。始终建议自行研究,判断哪种更适合你的项目。

我个人的看法是:默认始终使用 const,只有当你确实需要重新赋值时,才改用 let。

JavaScript入门

测验