原文:http://blog.gejiawen.com/2015/07/28/es6-new-feature/
ES6(ECMAScript 6)终于在2015年6月正式发布了。距离上一次正式公开的ES5(于2009年发布的)已经相距了不短的时间了。其实在ES6正式发布之前的一段时间内,ECMA组织已经不再向ES6中添加新特性了,所以其实在ES6正式发布之前,业界已经有许多对ES6的相关实践了。比如阮一峰的ECMAScript 6入门其实就是早于ES6的正式发布时间的。
本文将主要基于lukehoban/es6features,参考众多的博客文章资料,对新出的ES6中新增的特性做一个简介。后续本系列将会产出针对ES6不同特性的文章。
ES6新特性列表
下面的表格给出了ES6包含的所有特性,
新增特性 | 关键词 | 用法 | 描述 |
---|---|---|---|
箭头操作符 | Arrows | v => console.log(v) | 类似于部分强类型语言中的lambda表达式 |
类的支持 | Classes | - | 原生支持类,让javascript的OOP编码更加地道 |
增强的对象字面量 | enhanced object literals | - | 增强对象字面量 |
字符串模板 | template strings | ${num} | 原生支持字符串模板,不再需要第三方库的支持 |
解构赋值 | destructuring | [x, y] = ['hello', 'world'] | 使用过python的话,你应该很熟悉这个语法 |
函数参数扩展 | default, rest, spread | - | 函数参数可以使用默认值、不定参数以及拓展参数了 |
let、const | let、const | - | javascript中可以使用块级作用域和声明常量了 |
for…of遍历 | for…of | for (v of someArray) { ... } | 又多了一种折腾数组、Map等数据结构的方法了 |
迭代器和生成器 | iterators, generator, iterables | - | ES6较为难以理解的新东西,后面会有相关文章 |
Unicode | unicode | - | 原生的unicode更加完美的支持 |
模块和模块加载 | modules, modules loader | - | ES6中开始支持原生模块化啦 |
map, set, weakmap, weakset | - | - | 新的数据结构 |
监控代理 | proxies | - | 我们可以监听对象发生了哪些事,并可以自定义对应的操作 |
Symbols | - | - | 我们可以使用symbol来创建一个不同寻常的key |
Promises | - | - | 这家伙经常在讨论异步处理流程时被提到 |
新的API | math, number, string, array, object | - | 原生的功能性API就是方便些 |
内置对象可以被继承 | subclassable built-ins | - | 可以基于内置对象,比如Array,来生成一个类 |
二进制、八进制字面量 | - | - | 可以直接在es6中使用二进制或者八进制字面量了 |
Reflect API | - | - | 反射API? |
尾调用 | tail calls | - | ES6中会自动帮你做一些尾递归方面的优化 |
ok,上面就是es6中涉及到的所有的新增特性。下面我们针对每一个topic,举一个sample example加以说明,不过并不会深入阐述。
箭头操作符
何为箭头操作符?其实箭头操作符其实就是使用=>
语法来代替函数。如果你熟悉C#或者Java之类的强类型语音,你应该知道lambda语法,其实箭头操作符做的事情跟lambda表达式有异曲同工之妙。具体的用法看下面的例子,
1 | var arr = [1, 2, 3]; |
在传统写法中,我们需要写一个匿名的函数,然后给这个函数传入参数,在函数体中对此参数做相关处理。而使用箭头操作符后,它简化了函数的编写(其实是不需要再写匿名函数了)。
箭头操作符的左侧可以接收一个简单的参数,也可以使用一个参数列表。右侧进行具体的操作或者是返回值。下面的示例展示了箭头操作符更一般的用法,
1 | // 在表达式中使用 |
类的原生支持
ES6中提供了类的原生支持,引入了class
关键字,其实它是一种实现OOP编程思想的语法糖。它是基于原型链的。
其实javascript本身就是面向对象的语音,只不过没有Java之类的语言那么学院派,它更加灵活。ES6中提供的类其实就是对原型模型的包装。
ES6提供原生class
支持后,类方面的操作,比如类的创建、继承等等更加直观了。并且父类方法的调用、实例化、静态方法和构造函数等OOP概念都更加形象化了。
我们来看一些示例,看在ES6中到底如何使用学院化的使用类,
1 | // 类的定义 |
可以看到,ES6中我们可以完全用Java中的思想来写创建类、继承类、实例方法、初始化等等。
对象字面量的增强
在ES6中,对象字面量被增强了,写法更贱geek,同时可以在定义对象的时候做的事情更多了。比如,
- 可以在对象字面量里面定义原型
- 定义方法可以不用
function
关键字了 - 更加方便的定义方法
- 直接调用原型链上层(父层)的方法
具体的我们看下面的示例代码,
1 | var human = { |
字符串模板
ES6中提供原生的字符串模板支持。其语法很简单使用使用反引号`来创建字符串模板,字符串模板中可以使用${placeholder}来生成占位符。
如果你有使用后端模板的经验,比如smarty
之类的,那么你将对此不会太陌生。让我们来看段示例,
1 | var num = Math.random(); |
字符串模板其实并不是很难的东西,相对比较容易理解。个人觉得其目前主要的使用场景就是改变了动态生成字符串的方式,不再像以前那样使用字符串拼接的方式。
解构赋值
如果你熟悉python等语言,你对解构赋值的概念应该很了解。解构的含义简单点就是自动解析数组或者对象中值,解析出来之后一次赋值给一系列的变量。
利用这个特性,我们可以让一个函数返回一个数组,然后利用解构赋值得到数组中的每一个元素。让我们来看一些例子。
1 | function getVal() { |
函数参数的扩展
ES6中对函数参数作了很大的扩展,包括
- 默认参数
- 不定参数
- 扩展参数
默认参数,即我们可以为函数的参数设置默认值了。可能你在某些js库的源码经常会看到类似下面这样的操作,
1 | function foo(name) { |
上面的或操作其实就是为了给参数name
设置默认值。
而在ES6中,我们可以采用更加方便的方式,如下,
1 | function foo(name = 'larry') { |
不定参数的意思是,我们的函数接受的参数是不确定的,由具体的调用时决定到底会有几个参数。其实在ES6之前的规范中我们大可以使用arguments
变量来达到不定参数的判断,但是无疑这一方案过于复杂。
不定参数的用法是这样的,我们在函数参数中使用...x
这样的方式来代表所有的参数。其中x
的作用就是指代所有的不定参数集合(其实它就是一个数组)。让我们来看个例子,
1 | function add(...x) { |
关于拓展参数,其实拓展参数其实一种语法糖,它允许传递一个数组(或者类数组)作为函数的参数,而不需要apply
操作,函数内部可以自动将其当前不定参数解析,然后可以获得每一个数组(类数组)元素作为实际参数。看下面的示例,
1 | function foo(x, y, z) { |
新增let
和const
关键字
ES6中新增了两个关键字,分别为let
和const
。
let
用于声明对象,作用类似var
,但是let
声明的变量拥有更狭隘的作用域,脱离特定的作用域后变量的生命周期就终结了。这将有效的避免javascript中由于隐式变量作用域提升而导致的各种bug,甚至是内存泄露等等问题。
const
用于声明常量。
让我们来看一些例子。
1 | for (let i = 0; i < 2; i++) { |
for...of
遍历
ES6中新增了一种遍历数组和对象的方法,叫做for...of
。他与for...in
用法相似。看下面的例子,
1 | var arr = [1, 2, 3]; |
从上面的示例代码中,我们可以看出,for...of
遍历时提供的是value,而for...in
遍历提供的是key。
迭代器和生成器
ES6中新增的迭代器和生成器的相关概念相对来说有点复杂,后面将会产出专门的文章针对这个topic进行阐述。
Promise
Promises是处理异步操作的一种模式,之前在很多三方库中有实现,比如jQuery的deferred
对象。当你发起一个异步请求,并绑定了.when()
,.done()
等事件处理程序时,其实就是在应用promise模式。下面是一段示例代码,
1 | //创建promise |
关于promise更多的详细内容,后面将会产出专门的文章针对这个topic进行阐述。
Unicode的支持
ES6中对Unicode的支持更加完善了,可以使用使用正则表达式的u
标记对unicode字符串进行匹配。
1 | // same as ES5.1 |