每一个不曾起舞的日子都是对生命的辜负。
ES6 引入了 let 用作声明变量,用法和之前的 var 类似,但是声明之后的效果却有很大的区别。
let 声明的变量作用域是块级的(block scope),var 声明名的变量是函数级的(function scope)。let 声明的变量不存在作用域提升。不像 var,如果先使用后声明会取得值 undefined。如果先使用再用 let 声明,会报错。let 在同一作用域下,不允许重复声明,而 var 可以。const 声明一个只读的常量。
const 声明的常量,一旦声明,就必须立即初始化,不能留到以后赋值。const 声明的常量作用域和 let 相同,也是块级的。const 声明的常量也不存在作用域提升。let 一样,不能重复声明 const 常量。const 声明只是保证变量名所指向的地址不变,并不保证改地址保存的数据不变。ES6允许按照一定模式,从数组或对象中提取值,对变量进行赋值,被称为解构(Destructuring)。其用法和 Ruby、Scala 等的模式匹配(Pattern Match)比较类似。
只要等号两边的模式相同,等号左边的变量就会被赋予相应的值。有两种特殊情况,一种是等号右边的值不能被解构,这时左边的变量值为 undefined;另一种是不完全解构,即等号左边的模式只匹配右边部分值。
|
|
字符串可以被转换成类似数组的对象,因此也可以解构赋值。
|
|
函数的参数支持结构赋值,其规则和数组、对象的解构规则一致。
|
|
在 ES6 里面引入了模板字符串,用反引号标识。它可以当作普通单行字符串使用,也可以作为多行字符串使用,可以嵌入变量,函数调用。模板字符串中嵌入变量,需要将变量名或函数调用写在${ }之中。
|
|
JavaScript 在 ES6 之前,定义对象都是通过构造函数的方式进行的。如下
|
|
ES6 引入了 extends 关键字, class 之间可以通过 extends 很方便的实现继承。
|
|
这里在 constructor 和 toString 方法中都出现了 super 关键字。这个关键字有两种用法,一种是作为函数调用,此时 super 代表父类的 constructor 方法;另一种是作为对象调用,此时 super 代表的是父类,既可以应用父类实例的方法和属性,也可以引用父类的静态方法。如果子类定义了 constructor 方法,子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工。如果不调用 super 方法,子类就得不到 this 对象。这与 ES5 的继承有很大区别。如果子类没有显示定义 constructor 方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有 constructor 方法。
|
|
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这种用法和其他的面向对象语言中的静态方法很类似。而且父类的静态方法可以被子类继承,在子类的定义中,可以通过 super 来调用;也可以通过子类直接调用该静态方法。
|
|
遍历器(Iterator)作为一种机制,为各种不同的数据结构提供统一的访问机制。任何数据结构只要支持Iterator,就可以完成遍历操作。概况地讲,Iterator 有三个作用:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令 for…of 循环,Iterator接口主要供 for…of 消费。
Iterator的遍历过程是这样的:
ES6 提出的 class 语法糖,在很大程度上方便了面向对象编程,但是并没有解决模块化的问题。追溯 JavaScript 的历史,一直没有添加对模块化的支持,导致在构建大型的复杂的系统时,拆分依赖,按需加载都不是很容易的事情。这也是为什么各大公司、社区争相放出各种规范的原因,比如 AMD、CMD。
ES6模块的设计思想,是尽量的静态化,使得在编译时就能确定模块的依赖关系,以及输入和输出的变量。而CommonJS和AMD模块,都只能在运行时确定这些东西,所以不能很好的实现按需加载。ES6的模块不是对象,而是通过 export 语句显式指定输出的代码,输入时也采用静态命令的形式。
|
|
模块功能主要由两个语句构成: export 和 import 。 export 语句用于规定模块的对外接口, import 语句用于输入其他模块提供的功能。一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export 语句输出该变量。下面是一个JS文件,里面使用 export 语句输出变量。
|
|
使用 export 语句定义了模块的对外接口以后,其他JS文件就可以通过 import 语句加载这个模块(文件)。
|
|
引入变量的时候也可以进行重命名,比如:import { lastName as surname } from './profile';
从前面的例子中,我们可以看到,想要 import 部分函数的时候,类库的使用者必须要知道其中到底包含了哪些函数。这个时候为了给使用者提供方便,我们可以使用 export default来为模块指定默认输出参数。
|
|
上面的 export 中声明了一个匿名函数,然后输出为默认值。所以在 import 的时候我们可以指定任意名字,因此这时 import 语句后面,不使用大括号。当然 export default 也适用于非匿名函数。
|
|
上面例子中,函数名 foo 只在模块内部有效。加载的时候也会被视同为匿名函数。其实本质上,export default 就是输出一个叫做 default 的变量或函数,然后系统允许你为它取任意名字。
针对 ES6中的其他语法特性我就不在这里一一展开了,感兴趣的可以自行了解:Generator、Regular Expression、Symbol、Promise、Set、Map、Binary Array、Proxy、Reflect等。