ES6之let、const
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 })
- 使用let的循环
var func = []; for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }); }
- 在每次循环时,let声明都会创建一个新变量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 编译
在线实时编译地址:http://google.github.io/traceur-compiler/demo/repl.html
- 我们可以看到,let在循环中声明时,代码块的内容被单独拎出来形成了一个闭包。
至此,let、const知识点整理完毕。
参考书籍:
《深入理解ES6》[美] NICHOLAS C. ZAKAS 著 刘振涛 译