ES6常用新特性总结
前言
ECMAScript 6 简称 ES6,是 JavaScript 语言的下一代标准,已经在2015年6月正式发布了。本文对ES6标准中常用的一些特性进行介绍,需要注意的是,本文并不完整的涵盖ES6标准的规定,只是就我本人常用的特性进行总结。编写代码积极使用ES6特性能够使代码更加规范、易懂。
let和const关键字
在ES6中,推荐使用let和const关键字来代替var关键字用于声明变量。
let关键字相较于之前的var关键字更符合编程语言的常识,其具有以下特性:
- 具有块级作用域。
1 | { |
- 不允许重复声明。
1 | { |
- 不存在变量提升。
1 | console.log(a); // 使用var定义,输出变量默认值 undefined |
- 暂时性死区
在块级作用域中,在let声明变量之前,变量均是不可用的。
1 | var a = 'hello'; |
const关键字定义的变量是不可修改的,习惯上将使用const声明的变量使用全大写字母,且声明时必须给变量赋初值,此外,const特性和let关键字基本一致。
需要注意的是,const关键字只保证「字面意义」上的常量,例如,对于对象和数组而言,只是保证变量保存的地址值不被改变,并不能保证其管理的实际对象不改变:
1 | const ref = { |
尽量使用let和const关键词,避免使用var!
解构赋值
在ES6中,能够按照一定的匹配规则从数组或对象中提取值用于变量赋值。
- 从数组中解构赋值。
1 | let list = [1, 2, 3]; |
- 从对象中解构赋值。
1 | const person = { |
简化写法:
1 | // 当对象名和属性名一致时,可采用ES6中对象属性简洁写法: |
不完全解构:
1 | // 只解构出age属性 |
模板字符串
模板字符串用一对反引号标识,且字符串内可以使用${js表达式}
的形式嵌入js表达式,模板字符串可以标识多行字符串,空格和缩进均被保留。这极大的简化了以前js字符串拼接的麻烦。
1 | // 可以定义多行字符串,空格和缩进被保留 |
函数特性
默认参数
1 | // 默认参数,一般靠后 |
默认参数可以和解构赋值配合使用:
1 | const person = { |
ES6还支持rest参数,该参数形式为...varible
,该变量接收不定个数的参数作为一个数组(rest参数只能放在参数的最后,且只允许有一个rest参数):
1 | function printer(...res) { |
箭头函数
ES6允许使用箭头=>
定义函数:
1 | // 无参数箭头函数: |
特别的,当函数体只有一条语句,且需要返回值时,可以省略函数体的花括号:
1 | // 省略代码块适号: |
对象特性
方法和属性简写
ES6中,可以对对象的属性和方法采用简写形式:
1 | let name = '小明'; |
属性名表达式
ES6允许使用表达式作为属性名:
1 | let obj = { |
扩展运算符应用
扩展运算符将对象中所有可遍历的属性拷贝至新的对象上:
1 | const p1 = { |
此外,扩展运算符也可用于数组对象上:
1 | const arr1 = ['小明', '小红']; |
Symbol
ES6提供一种新的数据类型Symbol,表示独一无二的值,常用于解决命名冲突问题。
1 | // 以字符串为参数构造 |
以Symbol类型的值作为对象属性可以保证对象属性不重名:
1 | // 以字符串为参数构造 |
迭代器(iterator)
这里的迭代器和其它编程语言中的迭代器概念类似,也是给不同的数据结构提供了统一的接口。且ES6提供了一种新的遍历方式:for…of方式。
本质上,iterator是一个对象,这个对象提供了next()
方法,每次调用next()
方法返回一个形如{value: val, done : boolean}
的对象,分别表示当前返回的数据结构成员的值和是否遍历结束。
ES6规定,默认的iterator接口部署在数据结构的Symbol.iterator
属性上,该属性的值是一个函数,即迭代器生成函数,调用该函数会生成一个数据结构的迭代器。Symbol.iterator
属性名本身是一个表达式,是一个预定义好的类型为Symbol的值。
1 | let arr = [1, 2]; |
在ES6中,原生具有iterator接口的数据结构有:
- Array
- Map
- Set
- String
- TypedArray
- NodeList对象
- arguments对象
上述对象均可使用for…of直接遍历。
Promise对象
基础介绍
Promise
对象是ES6提供的一种解决异步编程问题的方案。Promise
保存着某个事件(通常为异步事件)执行的结果,该对象一共有三种状态:pending(未决,或进行中),fulfilled(已成功),rejected(已失败)。
ES6规定,Promise
对象是一个构造函数,用于生成实例。构造函数的参数为一个函数,这个函数有resolve
和reject
两个参数,且这两个参数均为函数,由js引擎提供。
1 | const p = new Promise(function(resolve, reject) { |
Promise
实例生成之后,可以使用then()
方法指定resolved
状态和rejected
状态的回调函数:
1 | p.then(function(value){ |
Promise对象封装Ajax请求
1 | const promise = new Promise(function(resolve, reject){ |
Promise.prototype.catch()
Promise.prototype.catch()
方法用于指定发生错误时的回调函数。
1 | promise.then(value => { |
async和await
async
和await
是用于简化异步操作的语法糖,使异步操作和同步操作一样简单。
async
函数返回一个Promise
对象,可以使用then
方法添加回调函数,且当函数执行时遇到内部的await
会先返回,等到异步操作完成后再执行函数体后面的语句。这个返回的Promise
的值为内部的return语句的值。当async
内部抛出错误时,返回的Promise
对象变为reject状态,可以用catch方法接收。
一般来说,await
命令后面是一个Promise
对象,其返回值是后面Promise
对象成功时的值,若后面Promise
对象失败了会抛出异常,需要在外面使用catch捕获。注:await
命令必须放在async
函数内部,这很容易理解,毕竟有await
一般就表示存在异步操作。
下面是一个通过商品id来获取商品价格的例子,函数内部存在两个异步操作,分别是getGoodsName
和获取getPrice
,它们返回值均是Promise
对象,故可以通过await
修饰来简化操作,且外部的函数需声明为async
。
1 | async getGoodsPrice(id) { |
模块化(export和import)
ES6允许编写多个js文件,并通过export将模块导出,通过import将模块导入。export本质上是对外暴露了一个变量或函数的访问接口,必须和模块内部的变量建立一一对应关系,通过这些暴露的接口,别人能够访问到模块内部的值。
- 分别导出
文件e.js中导出需要暴露的变量或函数:
1 | export var name = 'hello'; |
在文件i.js导入上述模块:
1 | // 注意变量名需保持一致 |
- 统一导出
文件e.js中导出需要暴露的变量或函数:
1 | var name = 'hello'; |
在文件i.js导入上述模块:
1 | // 注意变量名需保持一致 |
- 默认导出
文件e.js中导出需要暴露的变量或函数:
1 | // 默认导出一个对象 |
在文件i.js导入上述模块:
1 | // 针对默认导出模块,导入时可任意取名 |
此外,导入和导出时均可以使用as
对变量重新取名:
导出:
1 | // 导出时需按照新变量名来匹配 |
导入:
1 | // 导入重新命名变量 |
总结
本篇文章对部分常用的ES6标准特性进行了介绍,并不包含该标准的全部特性。