ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结(2)

简介: ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结(2)

8. async/await  

我们都知道使用 Promise 能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着 then,语义化不明显,代码不能很好地表示执行流程,那有没有比 Promise 更优雅的异步方式呢?那就是async/await!我们一起来揭开它神秘的面纱吧!

8.1  语法

 async函数中使用await,那么await这里的代码就会变成同步的了,意思就是说只有等await后面的Promise执行完成得到结果才会继续下去,await就是等待。请看下面的示例:

    function timeout () {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log(1);
          resolve()
        }, 1000);
      })
    }
    // 不加async和await是2、1   加了是1、2
    async function foo () {
      await timeout()
      console.log(2)
    }
    foo(); // 1, 2

8.2  使用场景

异步处理的逻辑都是使用同步代码的方式来实现的,而且还支持 try catch 来捕获异常,这感觉就在写同步代码,所以是非常符合人的线性思维的。

    async function foo () {
      try {
        let response1 = await fetch('https://www.baidu.com/')
        console.log(response1)
        let response2 = await fetch('https://juejin.im/')
        console.log(response2)
      } catch (err) {
        console.error(err)
      }
    }
    foo()

8.3  注意点

    ①  await 只能在 async 标记的函数内部使用,单独使用会触发 Syntax error;


    ②  await 后面需要跟异步操作,不然就没有意义了,而且 await 后面的 Promise 对象不必写 then ,因为 await 的作用之一就是获取后面 Promise 对象成功状态传递出来的参数。

8.4  async/await 的缺陷      

Async/await 让你的代码看起来是同步的,在某种程度上,也使得它的行为更加地同步。 await 关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样。它确实可以允许其他任务在此期间继续运行,但您自己的代码被阻塞。

这意味着您的代码可能会因为大量await的promises相继发生而变慢。每个await都会等待前一个完成,而你实际想要的是所有的这些promises同时开始处理(就像我们没有使用async/await时那样)。有一种模式可以缓解这个问题——通过将 Promise 对象存储在变量中来同时开始它们,然后等待它们全部执行完毕。

四、ES2018(ES9)

9. Object Rest & Spread

9.1  语法

        这块代码展示了 spread 语法,可以把 input 对象的数据都拓展到 output 对象,这个功能很实用。需要注意的是,如果存在相同的属性名,只有最后一个会生效。        

    const input = {
      a: 1,
      b: 2,
      c: 3
    }
    const output = {
      ...input,
      d: 4
    }
    console.log(output)  // {a: 1, b: 2, c: 3, d: 4}

9.2  注意点

如果属性的值是一个对象的话,该对象的引用会被拷贝,而不是生成一个新的对象。

    const obj = { x: { y: 10 } };
    const copy1 = { ...obj };
    const copy2 = { ...obj };
    obj.x.y = "jimmy";
    console.log(copy1, copy2); // x: {y: "jimmy"} x: {y: "jimmy"}
    console.log(copy1.x === copy2.x); // → true

10. for await of

异步迭代器(for-await-of):循环等待每个Promise对象变为resolved状态才进入下一步

10.1  我们知道 for...of 是同步运行的,看如下代码

    function timeout (time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(time)
        }, time)
      })
    }
    async function test () {
      let arr = [timeout(2000), timeout(1000), timeout(3000),]
      for (let item of arr) {
        console.log(Date.now(), item.then(console.log))
      }
    }
    test()

20210527153548522.png

10.2  ES9 中可以用 for...await...of 的语法来操作

       for await of 环等待每个Promise对象变为resolved状态才进入下一步。所有打印的结果为 2000,1000,3000

    function timeout (time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(time)
        }, time)
      })
    }
    async function test () {
      let arr = [timeout(2000), timeout(1000), timeout(3000),]
      for await (let item of arr) {
        console.log(Date.now(), item.then(console.log))
      }
    }
    test()

20210527153548522.png

11. Promise.prototype.finally()

        Promise.prototype.finally() 方法返回一个Promise,在promise执行结束时,无论结果是fulfilled或者是rejected,在执行then()和catch()后,都会执行finally指定的回调函数。这为指定执行完promise后,无论结果是fulfilled还是rejected都需要执行的代码提供了一种方式,避免同样的语句需要在then()和catch()中各写一次的情况。

11.1  语法  

    function test () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('success')
        }, 1000)
      })
    }
    test().then(res => {
      console.log(res);
    }).catch(err => {
      console.log(err);
    }).finally(() => {
      console.log('finally');
    })

11.2  使用场景

loading关闭

需要每次发送请求,都会有loading提示,请求发送完毕,就需要关闭loading提示框,不然界面就无法被点击。不管请求成功或是失败,这个loading都需要关闭掉,这时把关闭loading的代码写在finally里再合适不过了

五、ES2019(ES10)

12. Object.fromEntries()

方法 Object.fromEntries() 把键值对列表转换为一个对象,这个方法是和 Object.entries() 相对的。

12.1  示例1: Object 转换操作      

const obj = {
    name: 'jimmy',
    age: 18
}
const entries = Object.entries(obj)
console.log(entries)
// [Array(2), Array(2)]
// ES10
const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// {name: "jimmy", age: 18}

12.2  示例2: Map 转 Object        

    const map = new Map();
    map.set('name', 'Barry');
    map.set('age', 18)
    console.log(map); // Map(2) {'name' => 'Barry', 'age' => 18}
    const obj = Object.fromEntries(map)
    console.log(obj); // {name: 'Barry', age: 18}

12.3  示例3: 过滤  

    const course = {
      math: 80,
      english: 85,
      chinese: 90
    }
    const res = Object.entries(course).filter(([key, val]) => val > 80);
    console.log(res); // [ [ 'english', 85 ], [ 'chinese', 90 ] ]
    console.log(Object.fromEntries(res)); //{english: 85, chinese: 90}

13. Array.prototype.flat()

13.1  语法        

let newArray = arr.flat( depth )

  depth 可选, 指定要提取嵌套数组的结构深度,默认值为 1。

13.2  Demo 

   flat()  方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat());  //  [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2));  //  [0, 1, 2, [3, 4]]
//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// `flat()` 方法会移除数组中的空项:
var arr5 = [1, 2, , 4, 5];
arr5.flat(); // [1, 2, 4, 5]

14. Array.prototype.flatMap()

       flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。从方法的名字上也可以看出来它包含两部分功能一个是 map,一个是 flat(深度为1)。        

const numbers = [1, 2, 3]
numbers.map(x => [x * 2]) // [[2], [4], [6]]
numbers.flatMap(x => [x * 2]) // [2, 4, 6]

     对比下 map 和 flatMap 的区别

let arr = ['今天天气不错', '', '早上好']
arr.map(s => s.split(''))
// [["今", "天", "天", "气", "不", "错"],[""],["早", "上", "好"]]
arr.flatMap(s => s.split(''))
// ["今", "天", "天", "气", "不", "错", "", "早", "上", "好"]

15. String.prototype.trimStart()

trimStart() 方法从字符串的开头删除空格,trimLeft()是此方法的别名。    

String.prototype.trimEnd(), 就不介绍了,和下面类似;

let str = '   foo  '
console.log(str.length) // 8
str = str.trimStart() // 或str.trimLeft()
console.log(str.length) // 5

16. Symbol.prototype.description

    const name = Symbol('Barry')
    console.log(name); // Symbol(Barry) 
    console.log(name.toString()); // Symbol(Barry)
    console.log(name === 'Symbol(Barry)');  // false
    console.log(name.toString() === 'Symbol(Barry)'); // true

现在可以通过 description 方法获取 Symbol 的描述:

    const name = Symbol('Barry')
    console.log(name.description); // 'Barry'
    name.description = "es2" // 只读属性 并不能修改描述符
    // 如果没有描述符 输入undefined
    const age = Symbol();
    console.log(age.description); // undefined

17. JSON.stringify() 增强能力

 JSON.stringify 在 ES10 修复了对于一些超出范围的 Unicode 展示错误的问题。因为 JSON 都是被编码成 UTF-8,所以遇到 0xD800–0xDFFF 之内的字符会因为无法编码成 UTF-8 进而导致显示错误。在 ES10 它会用转义字符的方式来处理这部分字符而非编码的方式,这样就会正常显示了。

    \uD83D\uDE0E  emoji 多字节的一个字符
    console.log(JSON.stringify('\uD83D\uDE0E')) // 打印出笑脸
    如果我们只去其中的一部分  \uD83D 这其实是个无效的字符串
    之前的版本 ,这些字符将替换为特殊字符,而现在将未配对的代理代码点表示为JSON转义序列
    console.log(JSON.stringify('\uD83D')) // "\ud83d"

20210527153548522.png

18. 修订 Function.prototype.toString()

以前函数的 toString 方法来自 Object.prototype.toString(), 现在的 Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串。以前只会返回这个函数,不包含注释、空格等。      

    function foo () {
      // ES2019(ES10)
      console.log('ES2019(ES10)');
    }
    console.log(foo.toString());

20210527153548522.png

相关文章
|
前端开发
ES6、ES7、ES8、ES9、ES10、ES11新特性2
ES6、ES7、ES8、ES9、ES10、ES11新特性
|
JSON 前端开发 JavaScript
ES6、ES7、ES8、ES9、ES10、ES11新特性3
ES6、ES7、ES8、ES9、ES10、ES11新特性
|
2月前
|
JSON JavaScript 前端开发
浅谈ES5与ES6
浅谈ES5与ES6
37 3
|
前端开发 JavaScript Java
ES6、ES7、ES8、ES9、ES10、ES11新特性1
ES6、ES7、ES8、ES9、ES10、ES11新特性
|
前端开发 安全
说说你的ES7-ES12的了解
说说你的ES7-ES12的了解
|
前端开发 索引
ES7,ES8
ES7,ES8
62 0
|
JavaScript 前端开发 索引
ES9,ES10
ES9,ES10
71 0
|
前端开发 容器
ES6 Day04
ES6 Day04
77 0
|
前端开发 索引
ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结(1)
ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结(1)
ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结(1)