JavaScript ES6 let与const关键字详解:作用域、提升与常量机制

作者:木棉时间:2026-10-25 05:43:57浏览:461

本文深入解析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关键字内容,请搜索本站历史文章或继续阅读后续文章。感谢大家的支持!

作者最新文章