最近看了阮一峰的《ECMAScript6入门》 ,对第一章做一些记录
1. let命令
ES6 新增的关键字,用法就是用于声明变量,和 var 类似;区别在于声明的变量是局部的,只在 let 所在的代码块内有效。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
由于ES5中不存在块级作用域,变量i是var声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的function在运行时,会通过闭包读到这同一个变量i,导致最后输出的是最后一轮的i的值,也就是10。而如果使用let,声明的变量仅在块级作用域内有效,最后输出的是6。
同样的
for (let i = 0; i < 3; i++) { //子作用域
let i = 'abc'; //另一个子作用域
console.log(i);
}
// abc
// abc
// abc 因为两个i其实不一样,所以第二个i只会输出该作用域下的值
只要块级作用域内,存在 let 命令,它声明的变量就是绑定(binding)在这个区域,不受外部影响
var foo = 123 // 全局变量
if (true) {
console.log(foo) // ReferenceError: foo is not defined ,变量不提升,与var的区别之一
let foo
}
扫描二维码关注公众号,回复:
2868849 查看本文章
var tmp = 'abc';
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
所以要养成良好的变成习惯,变量声明之后再使用。
块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
const 声明的是一个只读的常量。一旦声明值便不可以改动。因为 const 声明的值并不能改变,所以声明的时候必须初始化
const PI = 3.1415926
console.log(PI) // 3.1415926
PI = 3 // TypeError: Assignment to constant variable.
const MAX // SyntaxError: Missing initializer in const declaration
const 的特点和 let 一样,只在声明的块级作用域中有效; const 声明的变量也不会提升,所以也是存在 TDZ 的;不能重复声明
再举个例子
const a = [];
a.push('Hello'); // 可执行,可写
a.length = 0; // 可执行
a = ['Dave']; // 报错 ,赋值不行
ES5 只有两种变量声明的方法: var 和 function 关键字;ES6 却还添加了 let , const , import , class ;所以 ES6 一共有6种声明变量的方法。