每一个不曾起舞的日子都是对生命的辜负。
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等。