2018都过一半了,还没来得及看ES8?

过了一个五一长期以后,发现2018年都过去一半了,尴尬的计划却赶不上时光的变化。javascript

1、函数参数容许尾后逗号

对于这个特性的更改,个人感触仍是很深的:每当删除或者添加函数末尾参数时,你不得不在前一个参数的后面删除或者添加逗号。这种操做很逆天。java

翻翻文档,其实早在ES5时代已经支持对象尾后逗号的书写,可是在JSON中是不容许尾后逗号的。web

Tip: JSON.stringify()会自动去掉对象的尾后逗号。app

2、String的padStart和padEnd

'咦嘻嘻'.padStart(10, '-') // -------咦嘻嘻
  '咦嘻嘻'.padEnd(10, '-')   // 咦嘻嘻-------
复制代码

Tip: 当长度小于字符串自己长度则返回字符串自己dom

看到这个方法,咱们不难会想起在此以前会经过什么方法去解决此类的问题。ecmascript

('----------' + '咦嘻嘻').slice(-10) // -------咦嘻嘻
复制代码

在ES6以前咱们能够经过slice加上固定的padString实现需求,显然缺点也很明显:padString的长度不够灵活。异步

('-'.repeat(10) + '咦嘻嘻').slice(-10) // -------咦嘻嘻
复制代码

进入ES6以后,咱们能够经过repeat结合slice实现,固然远没有padEnd来得方便。async

继表情包大战以后,聊天发表情,评论发表情几乎是随处可见。而咱们在字符串的处理中就须要注意emoji表情:函数

const s = '😀'
  s.length // 2
复制代码

因而可知,采用emoji做为padString时可能出现截断状况。fetch

console.log('咦嘻嘻'.padStart(10, s)) // 😀😀😀�咦嘻嘻
复制代码

虽然这是让人头疼的地方,可是emoji也有一些趣事

const s1 = '👨‍👩‍👦'
  [...s1] // [ '👨', '‍', '👩', '‍', '👦' ]
复制代码

3、Object的values和entries

这两个方法与ES5中的Object.keys()是相似的:

const fruits = {
    apple: 2,
    orange: 10
  }
  Object.keys(fruits) // [ 'apple', 'orange' ]
  Object.values(fruits) // [ 2, 10 ]
  Object.entries(fruits) // [ [ 'apple', 2 ], [ 'orange', 10 ] ]
复制代码

它们都是获取枚举属性而且不读取原型上的属性。

其实到这里,你们也会想起另外一种遍历对象的方法:

for (var key in fruits) {
    if (fruits.hasOwnProperty(key)) {
      console.log(key)
    }
  }
复制代码

没有对比就没有伤害,for-in就会读取原型上的属性,为了避免出现意想不到的错误,一般咱们会使用hasOwnProperty来过滤原型上的属性。

总结上面这四种遍历对象的方法,它们一个共同点就是只获取枚举属性,那么问题来了,若是想获取非枚举属性怎么办呢?

Object.defineProperty(fruits, 'peach', {
    value: 18,
    enumerable: false
  })

  Object.getOwnPropertyNames(fruits).filter(item => !fruits.propertyIsEnumerable(item)) // [ 'peach' ]
复制代码

这里细心的同窗可能还会发现一个问题:在ES6中为了解决字符串做为属性名带来的惟一性问题,能够采用Symbol做为属性名使用,那么Symbol属性名能书获取到吗?

Object.defineProperty(fruits, Symbol('banana'), {
    value: 20
  })
  Object.getOwnPropertySymbols(fruits) // [ Symbol(banana) ]
复制代码

这里,忽然想起了香锅的骚话,固然咱们要的是枚举属性、非枚举属性以及Symbol属性:

Reflect.ownKeys(fruits) // [ 'apple', 'orange', 'peach', Symbol(banana) ]
复制代码

4、Object上的另外一个方法 getOwnPropertyDescriptors

对于这个方法,你们应该不太陌生,由于在ES5中咱们定义对象时会采用:

const obj = {}

  Object.defineProperty(obj, 'name', {
    value: 'xiaoyun',
    enumerable: true,
    writable: true,
    configurable: true
  })
复制代码

而且会使用getOwnPropertyDescriptor获取它的描述器属性:

Object.getOwnPropertyDescriptor(obj, 'name')
复制代码

Tip: 采用对象字面声明的属性的描述器属性默认为true,采用defineProperty声明的属性的描述器属性的默认值为false

因此看到这个方法名,天然就知道它是干什么的:

Object.getOwnPropertyDescriptors(obj)
复制代码

固然,它的出现不只仅是由于这个问题。在ES6中新增的拷贝方法assign,它并不能处理描述器属性,因此涉及到描述器属性的对象,不能经过assign来拷贝,因此有了getOwnPropertyDescriptors方法以后,咱们能够这样处理设置描述器属性的对象:

Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj))
复制代码

5、async/await

对于这个新特性的出现,真是的是让人眼前一亮。

Tip:实际上async很早就被讨论了,以致于不少人认为它是ES6或者ES7标准,实际上它在2017才被正式列入标准,应该属于ES8标准。

对于async/await,你必需要知道:

  • async是用来声明一个异步函数,而且它默认返回一个Promise对象;
  • await操做符必须在async中使用;
  • await操做符后面必定是Promise对象,若是是普通对象,它会默认用Promise.resolve()包裹。
function fetchNumber () {
    return new Promise((resolve, reject) => {
      setTimeout(_ => {
        const num = Number.parseInt(Math.random() * 10)
        if (num >= 5) {
          resolve(num)
        } else {
          reject(new Error(`${num} is smaller than 5`))
        }
      }, 1000)
    })
  }

  async function task () {
    try {
      const num = await fetchNumber()
      return num
    } catch (e) {
      return Promise.reject(e.message)
    }
  }

  task().then(console.log).catch(console.log)
复制代码

在使用async时,千万不要由于它同步的写法而陷入误区,具体咱们须要分析咱们的异步,例如:咱们调用多个fetchNumber时,它们之间并无依赖关系,那么咱们应该这样写:

const [num1, num2] = await Promise.all([fetchNumber(), fetchNumber()])
复制代码

固然若是这两个方法有相互依赖的关系,那么就须要:

const num1 = await fetchNumber()
  const num2 = await fetchNumber()
复制代码

对于async的异常处理,基本上仍是采用try/catch的方式,固然也有对try/catch诟病的传送门

参考文章


    喜欢本文的小伙伴们,欢迎关注个人订阅号超爱敲代码,查看更多内容.

相关文章
相关标签/搜索