ECMAScript 6.0(简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布。
ES6新增语法:
-
let
-
ES6
新增了let
关键字,与var
类似,用于声明变量。
-
用
let
声明的变量只在它所在的代码块内有效{ var a = 10; let b = 20; } console.log(a); console.log(b);
for
循环的计数器,就很合适使用let
命令。使用
var
关键字声明的for
循环,在全局范围内都有效每次循环改变的是i
的值,函数内部的i
指向全局的i
,而此时for
循环早已结束,则i
输出的是for
循环最后一轮的值。var a = []; for (var i = 0; i < 5; i++) { a[i] = function() { console.log(i); } } a[3]();
使用
let
关键字声明的for
循环,此时的i
只在本轮的循环有效,每次循环的i
都是一个新的变量,JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算。var a = []; for (let i = 0; i < 5; i++) { a[i] = function() { console.log(i); } } a[3]();
另外使用
for
循环有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); }
-
2.
let
不存在变量提升
```javascript
console.log(a);
var a = 1;
console.log(b);
let b = 2;
```
3.暂时性死区
只要块级作用域内存在
let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。下面代码中,存在全局变量
tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。应该就是,只要在一个块级作用域内,存在
let
关键字,那么let
关键字初始化变量之前该变量不可用,即便全局作用域存在同名变量也不可用。凡是在声明之前就使用这些变量,就会报错。
-
总之,在代码块内,使用
let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。var tmp = 123; if (true) { //start TDZ tmp = 'abc'; let tmp;//end TDZ }
4.变量不允许重复定义
let
不允许在相同作用域内,重复声明同一个变量let
也不能重复声明var
声明过的变量var
也不能重复声明let
声明过的变量-
因此,不能在函数内部重新声明参数
let a = 1; let a = 2; //Uncaught SyntaxError: Identifier 'a' has already been declared var a = 1; let a = 2; //Uncaught SyntaxError: Identifier 'a' has already been declared
5.块级作用域
ES6 允许块级作用域的任意嵌套。
-
内层作用域可以定义外层作用域的同名变量。(外部不能使用内部定义的变量,但内部可以使用外部的变量)
{ let x = 1; { let y = 2; { let z = 3; let x = 'new1'; console.log(x); console.log(y); } } console.log(z); }
-
函数与块级作用域
-
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
if (true) { function a() {} } switch (1) { case 1: function b() {}; break; }
但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际都能运行,不会报错。
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于
let
,在块级作用域之外不可引用。-
如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
- 允许在块级作用域内声明函数。
- 函数声明类似于
var
,即会提升到全局作用域或函数作用域的头部。 - 同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作
let
处理。 所以,根据这三条规则,浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于
var
声明的变量。总之,考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
-
-
const
-
const
声明一个只读的常量。一旦声明,常量的值就不能改变;这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值。const ABC = 123; ABC = 456;
-
```javascript
const DEF;
//× Uncaught SyntaxError: Missing initializer in const declaration
```
-
const
的作用域与let
命令相同:只在声明所在的块级作用域内有效。{ const ABC = 123; } console.log(ABC);
-
const
命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。console.log(ABC); const ABC = 123;
-
const
声明的常量,也与let
一样不可重复声明。const ABC = 123; const ABC = 456; //Uncaught SyntaxError: Identifier 'ABC' has already been declared
ES6 声明变量的六种方法
ES5 只有两种声明变量的方法:var
命令和function
命令。ES6 除了添加let
和const
命令,后面章节还会提到,另外两种声明变量的方法:import
命令和class
命令。所以,ES6 一共有 6 种声明变量的方法。