ES2017 新特性:

  • async 函数
  • Object.values/Object.entries
  • 字符串填充:String.prototype.padStart()String.prototype.padEnd()
  • Object.getOwnPropertyDescriptors()
  • 函数参数列表和调用中的尾随逗号

async 函数

ES8 引入了 async 函数async 函数基本上是 co 的专用语法:

async function fetchJson(url) {
  try {
    let request = await fetch(url)
    let text = await request.text()
    return JSON.parse(text)
  }
  catch (error) {
    console.log(`ERROR: ${error.stack}`)
  }
}

在内部,async 函数的工作方式与 Generator 非常相似,但它们不会转换为生成器函数。

异步函数存在以下变体:

  • 异步函数声明:async function foo() {}
  • 异步函数表达式:const foo = async function () {}
  • 异步方法定义:let obj = { async foo() }
  • 异步箭头函数:const foo = async () => {}

更多资料

Object.values()

Object.values() 是一个与 Object.keys() 类似的新方法,但返回的是 Object 自身属性的所有值,不包括继承的值。

假设我们要遍历如下对象 obj 的所有值:

const obj = { 
  a: 1,
  b: 2,
  c: 3,
  [Symbol()]: 123
}

以前的写法如下:

const val = Object.keys(obj).map(key => obj[key])
console.log(val) // [1, 2, 3]

使用 Object.values()

const val = Object.values(obj)
console.log(val) // [1, 2, 3]

从上述代码中可以看出 Object.values() 为我们省去了遍历 key,并根据这些 key 获取 value 的步骤。

注意:您可能注意到了,它会忽略键为 Symbol 的属性,Object.keysObject.values,以及接下来的 Object.entries 也一样。

Object.entries()

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对的数组。

接下来我们来遍历上文中的obj对象的所有属性的 keyvalue

Object.keys(obj).forEach(key => {
  console.log(`key: ${key}, value: ${obj[key]}`)
})
// key:a value:1
// key:b value:2
// key:c value:3

使用 Object.entries()

for (let [key,value] of Object.entries(obj1)){
  console.log(`key: ${key} value:${value}`)
}
// key:a value:1
// key:b value:2
// key:c value:3

Object.entries() 还允许您通过对象设置 map。这比使用 2 元素数组的数组更简洁,但键只能是字符串。

let map = new Map(Object.entries({
  one: 1,
  two: 2,
}))

console.log(JSON.stringify([...map])) // [["one",1],["two",2]]

Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors() 方法返回对象的所有自身属性的属性描述符。如果没有,则返回空对象。

const obj = {
  name: 'UI',
  get age() { return 18 }
  [Symbol('foo')]: 123
}

console.log(JSON.stringify(Object.getOwnPropertyDescriptors(obj), null, 2))

/*
{
  "name": {
    "value": "UI",
    "writable": true,
    "enumerable": true,
    "configurable": true
  },
  "age": {
    "enumerable": true,
    "configurable": true
  }
}
*/

String.prototype.padStart() 和 String.prototype.padEnd()

在 ES8 中 String 新增了两个实例函数 padStart()padEnd(),其接受两个参数,第一个是重复次数,第二个是要添加的字符串,并在给定字符串的开头或结尾添加填充。

语法如下:

String.prototype.padStart(maxLength, fillString=' ')
String.prototype.padEnd(maxLength, fillString=' ')

如果字符串比 maxLength 短,使用 fillString 剩余长度:

'0.0'.padStart(5, '10') // '101.0'

如果字符串和 maxLength 一样长,或者比 maxLength 更长,则原样返回:

'abcd'.padStart(4, '*') // abcd
'abcdefg'.padStart(4, '*') // 'abcdefg'

如果 fillString 省略,则使用默认值,包含单个空格的字符串 (' ')

'x'.padStart(3)
'  x'

padEndpadStart 类似,一个用于开头,一个用于末尾。

函数参数列表和调用中的尾随逗号

在 ES8 之前,我们只有在对象字面量和数组字面量中的尾随逗号才被忽略:

let obj = {
  first: 'D.',
  last: 'O',
}

let arr = [
  'red',
  'green',
  'blue',
]
console.log(arr.length) // 3

它有两个好处:

  • 重新排列项目更简单,因为如果最后一个项目改变了它的位置,您不必添加和删除逗号。
  • 它帮助版本控制系统跟踪实际更改的内容。方便使用 Git 进行多人协作开发时修改同一个函数减少不必要的行变更。

鉴于可选和忽略尾随逗号的好处,建议的功能是将它们带到参数定义和函数调用中。

const foo = (a,) => {}

foo(a)
foo(a,)

(a) => {}(a,) => {} 都是有效的函数定义,foo(a)foo(a,) 都是有效的函数调用。