在早期 JavaScript 中,变量声明只有 var
这一种方式,在全局作用域和函数作用域中都可以使用。然而,由于变量的提升机制,导致一些不可预料的问题,比如重复声明变量或变量的声明与使用不在同一个作用域中。
为了解决这些问题,引入了 ES6 中的 let
和 const
,从而支持了块级作用域。在 ECMAScript 2020(简称 ES11)中,对 let
和 const
进行了一些改进和增强,同时引入了新的语法,本文将对这些内容进行详细介绍。
1. 块级作用域
块级作用域指的是在代码块中声明的变量只在该代码块内部可见,代码块可以是花括号 {}
括起来的任何内容,比如函数体、循环体、条件语句和代码块本身。使用块级作用域可以避免变量提升和变量污染等问题,也可以更加明确变量的作用范围。
使用 let
或 const
关键字声明的变量都有块级作用域。下面是一个简单的示例:
{ let a = 1; const b = 2; var c = 3; } console.log(a); // Uncaught ReferenceError: a is not defined console.log(b); // Uncaught ReferenceError: b is not defined console.log(c); // 3
可以看到,a
和 b
都在块级作用域中声明,并不能在外部访问,而 c
则是使用 var
声明,可以在全局作用域中访问。
2. 禁止重复声明变量
在早期 JavaScript 中,使用 var
声明变量时,可以重复声明同一个变量,而后面的声明会覆盖前面的声明,这容易导致误操作和不可预料的结果。使用 let
和 const
声明变量时,不能重复声明同一个变量,否则会抛出语法错误。
let a = 1; let a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared
const b = 1; const b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
3. TDZ 暂时性死区
由于使用 let
和 const
声明的变量具有块级作用域,所以在代码块内使用这些变量时,必须先声明,否则会抛出引用错误。这在 ES6 中称为 TDZ(Temporal Dead Zone,暂时性死区)。
console.log(a); // Uncaught ReferenceError: a is not defined let a = 1;
console.log(b); // Uncaught ReferenceError: b is not defined const b = 2;
在上面的示例中,变量 a
和 b
都在声明前被访问,因此抛出了引用错误。这是因为在变量声明前,它们已经存在于作用域中,但是不能被访问,因此处于暂时性死区内。
4. 全局对象属性
在早期 JavaScript 中,使用 var
声明的变量会成为全局对象的属性,可以通过 window
或 global
对象来访问。而使用 let
和 const
声明的变量不会成为全局对象的属性,这样可以避免全局变量造成的命名空间污染和安全问题。
var a = 1; console.log(window.a); // 1
let b = 2; console.log(window.b); // undefined
const c = 3; console.log(global.c); // undefined
需要注意的是,使用 let
和 const
声明的变量仍然可以在全局作用域内声明,但是不会自动成为全局对象的属性。
let a = 1; { let b = 2; } console.log(window.a); // 1 console.log(window.b); // undefined
5. const 常量
与 let
不同的是,使用 const
声明的变量是常量,不可修改。如果尝试修改常量的值,会导致语法错误。
const a = 1; a = 2; // Uncaught TypeError: Assignment to constant variable.
需要注意的是,使用 const
声明的变量不代表它所指向的值是不可变的,而是只保证变量本身不可修改。如果使用 const
声明的变量指向的是一个对象,可以修改对象的属性。
const obj = {a: 1}; obj.a = 2; console.log(obj.a); // 2
const arr = [1, 2, 3]; arr.push(4); console.log(arr); // [1, 2, 3, 4]
6. 静态方法 import.meta
ECMAScript 2020 引入了一个新的静态方法 import.meta
,用于访问模块元数据。可以通过 import.meta.url
获取模块文件的 URL,或者通过 import.meta.env
获取环境变量。
console.log(import.meta.url); console.log(import.meta.env);
需要注意的是,目前 import.meta
只能用于 ES6 模块中,不能用于 CommonJS 模块等其他方式的模块化。
7. 总结
学习 ES11 中的块级作用域变量声明 let
和 const
,可以避免变量污染和提升等问题,提高代码的可读性和可维护性。需要注意块级作用域、禁止重复声明、TDZ 暂时性死区、全局对象属性、const 常量和 import.meta 等内容,掌握这些知识可以更加灵活地使用 JavaScript,编写高质量的前端代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/649e47a248841e9894acff06