0%

ES2016-and-ES2017

说明

记录 ES2016 和 ES2017 相关知识

ES2016

指数运算符

x ** y 等价于 Math.pow(x, y)

1
2
console.log(2 ** 3) // 8
console.log(Math.pow(2, 3)) // 8

注意

  • ** 的左侧一元表达式只能使用 ++--
1
2
let result1 = (-5) ** 2 // 25
let result2 = -5 ** 2 // SyntaxError: Unexpected token **
1
2
3
4
5
6
7
8
let num1 = 2
let num2 = 2

console.log(++num1 ** 2) // 9
console.log(num1) // 3

console.log(num2-- ** 2) // 4
console.log(num2) // 1
  • ** 幂运算是右结合的
1
2
console.log(2 ** 3 ** 2) // 512
console.log(2 ** (3 ** 2)) // 512

Array.prototype.includes()

接受两个参数,返回值为 true(找到)或 false (没找到)

  • 要搜索的值
  • 开始搜索的索引位置,可选参数
1
2
3
4
let values = [1, 2, 3]
console.log(values.includes(1)) // true
console.log(values.includes(1, 1)) // false
console.log(values.includes(0)) // false

注意

  • indexOf() 方法传入 NaN 会返回 -1,无论数组是否包含 NaN,includes() 方法则可以区分
1
2
3
let values = [1, NaN, 3]
console.log(values.indexOf(NaN)) // -1
console.log(values.includes(NaN)) // true
  • +0 和 -0 被认为是相等的,indexOf 和 includes() 处理一致
1
2
3
let values = [1, -0]
console.log(values.indexOf(+0)) // 1
console.log(values.includes(+0)) // true

严格模式

只有参数不包含 解构 或 默认值 的函数中才可以在函数体中使用 ‘use strict’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 正常
function okay(first, second) {
'use strict'
return first+second
}

// SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list
function notOkay1(first, second=first) {
'use strict'
return first+second
}

// 同 notOkay1 报错
function notOkay2({first, second}) {
'use strict'
return first+second
}

ES2017

Async functions

使用

1
2
3
4
async function fnName() {}
const foo = async function() {}
let obj = {async foo() {}}
const foo = async () => {}
  • 统一定义 wait 函数,下面用到
1
2
3
4
5
6
7
function wait(sec) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(sec)
}, sec * 1000)
})
}

返回值是 Promise 对象

  • async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数
1
2
3
4
5
6
async function asyncFunc() {
return 123
}

asyncFunc().then(x => console.log(x))
// 123

await 命令

  • await命令只能用在async函数之中,如果用在普通函数,就会报错
  • await 命令后面如果是一个 Promise 对象,则返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。
1
2
3
4
5
async function f() {
// 等同于
// return 123
return await 123
}
  • await 命令后面是一个 thenable 对象(即定义 then 方法的对象),那么 await 会将其等同于 Promise 对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Sleep {
constructor(timeout) {
this.timeout = timeout
}
then(resolve, reject) {
const startTime = Date.now()
setTimeout(() => resolve(Date.now() - startTime), this.timeout)
}
}

;(async () => {
const actualTime = await new Sleep(1000)
console.log(actualTime) // 1002【该值不确定】
})()

Promise 对象的状态变化

async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误。

1
2
3
4
5
6
7
8
9
10
11
async function test() {
let res = await wait(2)
console.log('res', res)
return res
}

console.log('done', test())

// done Promise { <pending> }
// 等 2s
// res 2

错误处理

  • 如果 await 后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject
1
2
3
4
5
6
7
8
9
10
async function f() {
await new Promise(function(resolve, reject) {
throw new Error('出错了')
})
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// Error:出错了
  • 可以使用 try..catchasync 函数内处理错误,或通过 catchasync 函数内处理错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function f() {
try {
await wait(2)
} catch (err) {
console.log(err)
}
}

// 等价于
function f() {
return wait(2).catch(err => {
console.log(err)
})
}

继发 & 并行

  • 多个 await 命令后面的异步操作,如果不存在继发关系,可以让它们并行触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 写法一
let [one, two, three] = await Promise.all([wait(1), wait(2)])

// 写法二
let onePromise = wait(1)
let twoPromise = wait(2)
let one = await fooPromise
let two = await barPromise

// 写法三
let arr = [1, 2]
arr.forEach(async v => {
let res = await wait(v)
console.log('forEach', res)
})
1
2
3
4
5
6
7
8
9
10
11
async function asyncFunc() {
const result = await otherAsyncFunc()
console.log(result)
}

// 等价于
function asyncFunc() {
return otherAsyncFunc().then(result => {
console.log(result)
})
}
  • 处理继发关系
1
2
3
4
5
6
7
8
let arr = [1, 2, 3]
async function doFun() {
for (let v of arr) {
let res = await wait(v)
console.log('for..of', res)
}
}
doFun()

执行顺序

async 函数同步开始,异步解决

1
2
3
4
5
6
7
8
9
10
11
12
13
async function asyncFunc() {
console.log('A asyncFunc()') // (A)
return 'abc'
}

asyncFunc().then(x => console.log(`B Resolved: ${x}`)) // (B)

console.log('C main') // (C)

// 依次输出
// A asyncFunc()
// C main
// B Resolved: abc
  1. The result of an async function is always a Promise p. That Promise is created when starting the execution of the async function.
  2. The body is executed. Execution may finish permanently via return or throw. Or it may finish temporarily via await; in which case execution will usually continue later on.
  3. The Promise p is returned.

参考

参考链接:http://exploringjs.com/es2016-es2017/

参考链接:http://es6.ruanyifeng.com/#docs/async

参考书籍:《UNDERESTANDING ECMASCRIPT 6》