当我们决定学习诸如Vue等前端框架时,了解ES6标准是至关重要的入门知识。回想起刚开始工作时,我们后端也需要掌握和参与前端的一些技术,每周都有一次小组内部答辩。而首次考察的主题就是ES6中的let和const。今天,让我们一起来深入了解ES6以及let和const的相关知识。
ES6简介
ES6是ECMAScript 6.0的简称,它是JavaScript语言的一次重大更新,引入了许多新特性和语法改进,包括但不限于:
- 块级作用域声明:包括let和const。
- 箭头函数:提供更简洁的函数定义语法。
- 模板字符串:使用反引号 (`) 包裹字符串,并允许嵌入表达式。
- 类(Class):引入了基于原型的面向对象编程的新语法。
- 模块(Module):支持模块化编程,使用import和export关键字。
- 增强的对象字面量:支持更简洁的对象属性和方法定义。
- 符号(Symbol):一种新的基本数据类型,用于创建唯一的标识符。
- 迭代器和生成器:用于控制循环行为和生成序列值。
- Promise:用于处理异步操作。
ES6的发布使得JavaScript语言更加现代化、强大和易用,为开发者提供了更多工具和选择。
在ES6之前,JavaScript语言的功能和语法相对较为古老和有限,缺乏许多现代编程语言的特性,导致在大型项目开发中容易出现混乱和难以维护的情况。ES6的推出填补了这些不足,使得JavaScript在功能和性能上有了长足的进步,也更好地适应了当今复杂的Web应用开发需求。
let和const命令
let命令
- 基本用法
let是ES6新增的命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。示例如下:
{
var testVat = 6;
let testLet = 8;
console.log("testVat = "+testVat); // testVat = 6
console.log("testLet = "+testLet); // testLet = 8
}
- 在for循环中使用
let 声明的变量具有块级作用域。在每次循环迭代中,for 循环的 let i 变量会在每个新的迭代中重新声明,因此每次循环都会拥有一个新的变量域。
具体来说,使用 let 声明的变量在 for 循环中,每次迭代都会创建一个新的变量绑定。这与 var 的行为不同,var 声明的变量在函数级别上是共享同一个变量的。
例如 let :
for (let i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 500);
}
// 输出0 到 9
在这个例子中,由于 let 在每次循环中都创建了一个新的绑定,所以每次 setTimeout 回调函数执行时,i 都是不同的,输出将是 0 到 9。
注: 如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
for (var i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 500);
}
// 每次输出10
在这种情况下,var 声明的 i 变量在整个循环过程中是共享的,所以当 setTimeout 回调函数执行时,i 的值已经变成了 10(循环结束后的值),因此会输出 10 十次。
- 不能重复声明
let 不允许在相同作用域内,重复声明同一个变量,而var 可以
//在同一个作用域内var可以重复声明
var test = 'xj';
var test = '修己xj';
//let重复声明会报错 SyntaxError: Identifier 'testLet' has already been declared.
let testLet = 'xj';
let testLet = '修己xj';
- 不存在变量提升
//var
console.log(testVar); // undefined
var testVar = 5;
//let
console.log(testLet); // Error in created hook: "ReferenceError: Cannot access 'testLet' before initialization"
let testLet = 5;
- 暂时性死区
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
var test = 'xj';
if(true){
test = '修己xj';
let test ;
}
以上代码会报错:ReferenceError: Cannot access 'test' before initialization
const命令
- 基本用法
const 声明一个只读的常量。一旦声明,常量的值就不能改变。
const TEST_CONST = 'xj';
TEST_CONST = '修己xj';
//报错 TypeError: Assignment to constant variable
const一旦声明变量,就必须立即初始化。
const TEST_CONST ;
//报错 SyntaxError: Missing initializer in const declaration.
其它使用和let是一致的。
- 本质
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
比如:
const TEST_CONST = {
'name':'修己xj',
'age': 30
};
console.log(TEST_CONST);
TEST_CONST.name = '修己';
TEST_CONST.other = '帅气逼人';
console.log(TEST_CONST);
var, let 和 const对比
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
提升 | 有 | 无 | 无 |
重复声明 | 允许 | 不允许 | 不允许 |
必须初始化 | 否 | 否 | 是 |
重新赋值 | 允许 | 允许 | 不允许 |
总结
ES6 为JavaScript带来了许多强大的新特性,使开发者能够编写更加简洁、清晰和高效的代码。let和const作为新的变量声明方式,提供了更严格的作用域控制和不可变性,有助于减少错误和提高代码质量。在今后的开发中,我们应当充分利用这些新特性,写出更加现代和健壮的JavaScript代码。