JavaScript ES6 let与const关键字详解:作用域、提升与常量机制
本文深入解析JavaScript ES6引入的let与const关键字。重点阐述let的块级作用域特性、变量提升机制及暂时性死区(TDZ)概念,说明其如何避免var的变量提升问题。同时详细讲解const声明常量的不可变性原理,区分基本类型与复合类型(数组、对象)在内存地址与内容修改上的差异,帮助开发者规范变量声明并避免常见运行时错误。
1. let关键字
1.1 基本用法
let是ECMAScript 2015新增的关键字,用于声明变量。其基本用法与var相似,但核心区别在于:let声明的变量仅在当前代码块内有效。
其语法结构如下:
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
参数说明:
var1, var2, …, varN:变量名,必须是合法的标识符。
value1, value2, …, valueN:变量的初始值,可以是任意合法的表达式。
示例代码如下:
在全局作用域中定义变量。
// 定义全局变量
var a = 100; // 使用 var 关键字
let b = 200; // 使用 let 关键字
console.log(a); // 100
console.log(b); // 200
从上述代码可以看出,在全局作用域下,let与var定义变量的行为看似没有区别。
在块作用域中定义变量。
关于块级作用域的更多细节可参考相关文档。
// 在块作用域中定义变量
{
var a = 100; // 使用 var 关键字
let b = 200; // 使用 let 关键字
}
console.log(a); // 100
console.log(b); // 抛出异常,描述信息为 ReferenceError: b is not defined
当let在代码块中使用代码块时,该代码块构成一个全新的作用域。在此作用域外部,无法访问该变量。
ES6提供的let关键字特别适合用作for循环计数器。若使用let声明循环变量,该变量仅在循环体内有效,一旦跳出循环体尝试访问,便会抛出异常。
示例代码如下:
// 定义一个循环体
for (let v = 0; v < 10; v++) {
console.log("这是一个 for 循环"); // 这是一个 for 循环 * 10
}
console.log(v); // 抛出异常,描述信息为:ReferenceError: v is not defined
值得注意的是,for循环存在一个特殊机制:设置循环变量的部分构成父作用域,而循环体内部构成独立的子作用域。
示例代码如下:
for (let v = 0; v < 10; v++) {
let v = 10
console.log(v); // 100 * 10
}
上述结果证实,每次循环迭代中的变量v并不处于同一个作用域。
1.2 不存在变量提升
若使用var定义变量,会发生变量提升现象,代码如下:
console.log(v); // undefined
var v = 100;
在变量声明之前使用该变量,程序不会报错,但结果为undefined。这违背了常规逻辑,按常理此时应抛出异常。
在ECMAScript 2015中,let关键字修正了这一现象。
代码如下:
console.log(v); // 抛出异常 描述信息为 ReferenceError: Cannot access 'v' before initialization
let v = 100;
执行上述代码会抛出异常,提示信息为“在声明之前不能使用某变量”。
1.3 暂时性死区
只要块级作用域内存在let定义的变量,该变量便绑定于此区域,不再受外部影响。示例代码如下:
let v = 100;
{
console.log(v); // 抛出异常 描述信息为 ReferenceError: Cannot access 'v' before initialization
// 此变量绑定在该块级作用域中,该作用域只能只用此变量
let v = 200;
}
ECMAScript 2015明确规定,若区块中存在let关键字,则该区块对这些命令声明的变量自始至终形成封闭作用域。若在声明前使用这些变量,将直接报错。
综上所述,在块级作用域中,使用let声明变量前,该变量不可用。这种语法现象称为暂时性死区(Temporal dead zone,简称TDZ)。
1.4 不允许重复声明
ECMAScript 2015提供的let关键字禁止重复声明,这与var不同。示例代码如下:
// 使用 var 声明变量
var a = 100;
console.log(a); // 100
var a = 1000; // 重复声明
console.log(a); // 1000
// 使用 let 声明变量
let b = 100;
console.log(b); // 100
let b = 1000; // 重复声明
console.log(b); // 抛出异常 描述信息为:SyntaxError: Identifier 'b' has already been declared
若尝试重复声明,将抛出SyntaxError异常。
1.5 与函数的关系
函数参数相当于使用let定义的变量。若在函数体内使用let重新声明与参数同名的变量,将抛出SyntaxError异常。此外,函数体内使用let同样不允许变量提升。
// 使用 let 声明变量
let a = 100;
// 定义一个函数
function fun(b) {
// let b = 10; // 抛出异常,描述信息为:SyntaxError: Identifier 'b' has already been declared
console.log(a); // 抛出异常,描述信息为:ReferenceError: Cannot access 'a' before initialization
let a = 200;
}
fun(20)
2. const关键字
2.1 基础用法
const关键字用于声明常量。可将const生成的常量视为具有不可变特性的let变量,它继承了let的所有特性并增加了不可变性。
常量在初始化后不可更改,且声明时必须初始化。示例代码如下:
const a = 2
a = 3 // 抛出异常
const b // 未初始化抛出异常
然而,若通过const初始化对象或数组,可以修改其内部属性或元素,程序不会报错。示例代码如下:
const arr = []
arr[0] = 100
console.log(arr) // [100]
const obj = {}
obj.name = '一碗周'
console.log(obj) // {name: "一碗周"}
出现此现象的原因是,const保证的并非变量值的不可变,而是变量指向的内存地址不可变。对于基本数据类型,如String、Number、Boolean,值直接存储在变量指向的内存地址中,因此不可二次修改。
对于复合类型数据,主要指Array和Object,变量指向的内存地址中存储的是指针。const仅保证该指针指向的内存地址固定,至于该地址中存储的数据结构是否可变,则不受控制。
在实际开发中,建议避免使用var关键字,优先使用const关键字;仅在需要重新赋值时使用let关键字。
本文关于JavaScript ES新特性let与const关键字的介绍至此结束。如需了解更多ES新特性let与const关键字内容,请搜索本站历史文章或继续阅读后续文章。感谢大家的支持!
JS合并多个数组的三种方法:concat、spread与flat
2026-11-05 17:39:45
JavaScript怎么准确判断数据类型:typeof、instanceof与Object.prototype.toString
2026-11-05 17:09:21
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
