ES6之let、const
在ES6中加入了两种变量的声明方式:
- 可以改变的变量关键字:
let
- 不可以改变的变量关键字:
const
let
和const
与var
关键字的区别
let
和const
用于块级声明
- 块级作用域(词法作用域)
- 在同一作用域不可以重复声明; 嵌套的作用域,可以同名。
function exampleFunction () { // 函数内部,一个块级区域
let a = 1;
const b = 1;
if (true) { // {}之间的块区域
let a = 2; // 合法
const b =2; // 合法
}
}
变量提升和TDZ
- 变量提升:在函数作用域或全局作用域中通过关键字
var
声明的变量,无论是在哪里声明的,都会被当成在当前作用域顶部声明的变量。
function varExample(flag) {
if (flag) {
var a = 1;
}
console.log(a) // flag 为 true,输出 1,
// flag 为 false,输出 undefined,
}
实际js引擎会这样解析
function varExample(flag) {
var a;
if (flag) {
a = 1;
}
console.log(a) // flag 为 false时,a已定义、但未赋值,因此返回 undefined.
}
TDZ
(Temporal Distortion Zone): 临时死区
var
声明的变量会发生变量提升,而let
和const
声明的变量会放在一个‘小黑屋’里。只会在变量声明之后,才能将变量放出来。
function tdzFunction() {
console.log(typeof a); // 还在TDZ内,访问报错,提示声明前不可访问
let a = 1;
console.log(typeof a); // 正常输入类型 number, 当然前面的报错要先屏蔽一下
}
- 特殊处理:循环中的块作用域绑定
- 用
var
的循环,在其中使用立即调用表达式(IIFE)
var func = [];
for (var i = 0; i < 10; i++) {
funcs.push((function(value) {
return function() { // 此处若不返回函数,push入数组的将是执行后的结果undefined
console.log(value);
}
}(i)));
}
funcs.forEach(function(func) {
func(); // 0, 1, 2, ... 9
})
var func = [];
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i)
});
}
// 伪代码
(let i = 0) {
funcs[0] = function() {
console.log(i)
}
}
(let i = 1) {
funcs[1] = function() {
console.log(i)
}
}(let i = 2) {
funcs[2] = function() {
console.log(i)
}
}
......
- const 不能使用在普通的for循环中,因为
i++
时重新赋值会报错。 - for-of、for-in循环中,key值是一种引用关系,因此与let用法一致。
babel 编译
- 我们可以看到,let在循环中声明时,代码块的内容被单独拎出来形成了一个闭包。