美文网首页Javascript
ES6/ES7/ES8常用特性和新特性

ES6/ES7/ES8常用特性和新特性

作者: cs0710 | 来源:发表于2018-10-09 15:40 被阅读258次

    ES6

    ES6在ES5的基础上新增了一系列特性,这里仅列出常用特性

    • 变量的改变,添加了块级作用域的概念

      let声明变量(块级作用域),let是更完美的var,它声明的全局变量不是全局属性widow的变量,这便解决了for循环中变量覆盖的问题

      const声明常量(会计作用域)

      // var
      var a = [];
      for (var index = 0; index < 10; index++) {
      
        a[index]=function () {
            console.log(index);// index会向上查找a作用域的index值
        }
      
      }
      console.log(index); // 10
      a[6](); // 10
      
      // let
      const a = [];
      for (let index = 0; index < 10; index++) {
        a[index]=function () { console.log(index); }  // index只在本轮循环中生效,每一次循环都会新建一个变量
      }
      a[6](); // 6
      console.log(index); // index not defined
      
    • 字符串新增方法

      let str = 'happy';
      console.log(str.includes('ha')) // true
      console.log(str.repeat(3)) // 'happyhappyhappy'
      console.log(str.startsWith('ha')); // true,参数2为查找的位置
      console.log(str.endsWith('p', 4)); // true,参数2为查找的字符串长度
      
    • 函数可以像C/C++那样设置默认参数值,增加数据容错能力

    • 对象

      • 键值对重名简写

        function people(name, age) {
            return {
                name,
                age
            };
        }
        
      • 对象字面量简写

        const people = {
            name: 'lux',
            getName () {    // 省略冒号(:) 和function关键字
                console.log(this.name)
            }
        }
        
      • 提供对象对象合并

        const obj1 = {
          a: 1
        }
        const obj = Object.assign({c: 2}, obj1)
        console.log(obj);
        
      • 数据解构和rest参数

        // 对象解构
        const people = {
            name: 'cs',
            age: 25
        }
        const { name, age } = people; // 'cs', 25
        
        // 数组解构 
        const arr = [1, 3, 4];
        const [a, b, c] = arr; // 1, 3, 4
        
        // rest参数,返回的是一个对象
        const obj = {a: 2, b: 3, c: 4, d: 5};
        const {a, ...rest} = obj; // 2 { b: 3, c: 4, d: 5 }
        
      • 数据展开

        // 展开对象(和上面Object.assign()一样,也是对象合并)
        const obj = {a: 2, b: 3}
        console.log({...obj, c: 5});// {a 2, b: 3, c: 5}
        // 展开数组
        const arr = [1, 3, 4]
        console.log([...arr, 5]); // [1, 3, 4, 5]
        
      • Promise

      Promise作为ES6的重要特性之一,被ES6列为正式规范。在控制台打印出来Promise是一个构造函数。参见:https://www.cnblogs.com/lvdabao/p/es6-promise-1.html

      Promise.png

    可以看到上面的Promise自身有我们常用的all、race、resoleve、reject等方法,原型中还有catch、then等方法,所以我们创建Promise实例时,将then会作为callback使用,避免回调地狱的出现。

    // resolve、reject的使用
    function getNum() { 
      const randomNum = Math.ceil(Math.random() * 10);
      return new Promise((resolve, reject) => {
        if (randomNum > 5) {
          resolve('大于5');
        } else {
          reject('小于5');
        }
      })
    }
    getNum().then((result) => {
      console.log('success', result);
      
    }).catch((err) => {
      console.log('err', err);
    });
    

    使用catch方法和then的第二个参数的效果一样,但是它还有你另外一个作用,那就是在then的第一个resolve回调函数中代码出错,不用卡死js的执行,而是会进入到catch中,捕获err原因。

    Promise.all的提供了并行的操作能力,并且是在所有的一步操作执行完成后才执行回调。all接收一个数组参数,它会把所有异步操作的结果放进一个数组中传给then。

    // all的使用
    function async1 () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('async1');
          resolve('async1完成')
        }, 1000);
      })
    }
    
    function async2 () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log('async2');
          resolve('async2完成')
        }, 2000);
      })
    }
    
    function async3 () {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
        console.log('async3');
          resolve('async3完成')
        }, 3000);
      })
    }
    Promise.all([async1(), async2(), async3()]).then((result) => {
      console.log(result);
      // do something...
    }).catch((err) => {
      console.log(err);
    });
    
    // result:
    async1
    async2
    async3
    [ 'async1完成', 'async2完成', 'async3完成' ]
    

    该方法适用于游戏类一些场景,所有素材、静态资源请求都加载完成,在进行页面的初始化

    race也提供了并行的操作能力,和all方法相反,大白话就是:all是以函数中执行最慢的那一个为准,race是以函数中执行最快的那一个为准。race接收一个数组参数,它会把执行最快的那个异步操作的结果传给then。

    // 以上面的三个异步操作函数为例
    Promise.race([async1(), async2(), async3()]).then((result) => {
     console.log(result);
    }).catch((err) => {
     console.log(err);
    });
    // result:
    async1
    async1完成
    async2
    async3
    

    该方法适用于请求超时的场景,比如请求图片资源,超过5秒就reject操作。

    function requestImg() {
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         resolve('请求图片资源')
       }, 6000);
     })
    }
    function timeout() { 
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         reject('请求超时');
       }, 3000);
     })
    }
    Promise.race([requestImg(), timeout()]).then((result) => {
     console.log(result);
    }).catch((err) => {
     console.log(err);
    });
    // result:
    请求超时
    

    上面在请求超时完成后,其实requestImg()函数并没有停止执行,而是不会再进入resolve的回调函数中了。

    • Set

      Set作为ES6新的数据解构(类数组),它的成员都是唯一的,因为最直接的使用场景便是去重、并、差、交集的使用。它使用的算法叫做“Same-value-zero equality”,类似精确运算的===,主要是NaN,这里它将两个视为相等。参见:http://es6.ruanyifeng.com/#docs/set-map#Set

      // Set实例的常用方法和属性add,delete,clear,has、size
      const s = new Set(['A', 'B', 'C']);
      console.log(s); // Set { 'A', 'B', 'C' }
      console.log(s.has('A')) // true,bool值
      console.log(s.size) // 3
      console.log(s.clear()) // Set {}
      console.log(s.delete('A')) // true,bool值
      

      同时Set实例配合常用遍历方法,实现并、交、差集。

      const a =[1, 2, 3]
      const b = [2, 3, 4];
      // 并集
      const s = Array.from(new Set([...a, ...b])); // [ 1, 2, 3, 4 ]
      // 交集、差集
      const bSet = new Set(b);
      const interestSet = a.filter(v => bSet.has(v)); // [ 2, 3 ]
      const interestSet = a.filter(v => !bSet.has(v)); // [ 1 ]
      

    ES7

    ES7在ES6的基础上添加三项内容:求幂运算符(**)、Array.prototype.includes()方法、函数作用域中严格模式的变更。

    • 求幂运算符(**),这是一个中缀例子,效仿自Ruby等语法,使用更简洁

      Math.pow(3, 2) === 3 ** 2    // 9
      
    • Array.prototype.includes()

      数组原型的方法,查找一个数值是否在数组中,只能判断一些简单类型的数据,对于复杂类型的数据无法判断。该方法接受两个参数,分别是查询的数据和初始的查询索引值。

      [1, 2, 3].indexOf(3) > -1 // true
      等同于:
      [1, 2, 3].includes(3) // true
      

      两者的优缺点和使用场景

      • 简便性

        includes方法略胜一筹,直接返回bool。indexOf需要返回数组下标,我们需要对下标值在进行操作,进而判断是否在数组中。

      • 精确性

        两者这都是通过===进行数据处理,但是对NaN数值的处理行为不同。includes对NaN的处理不会遵循严格模式去处理,所以返回true。indexOf会按照严格模式去处理,返回-1。

        [1, 2, NaN].includes(NaN)     // true
        [1, 2, NaN].indexOf(NaN)  // -1
        

      • 使用场景

        如果仅仅查找数据是否在数组中,建议使用includes,如果是查找数据的索引位置,建议使用indexOf更好一些

    ES8

    • async、await异步解决方案

      提出场景有两个:JS是单线程、优化回调地狱的写法。

      this.$http.jsonp('/login', (res) => {
        this.$http.jsonp('/getInfo', (info) => {
          // do something
        })
      })
      

      在ES6中为了解决回调的书写方式,引入了Promise的then函数,业务逻辑很多的时候,需要链式多个then函数,语义会变得很不清楚。

      new Promise((resolve, reject) => {this.login(resolve)})
      .then(() => this.getInfo())
      .then(() => {// do something})
      .catch(() => { console.log("Error") })
      
      

      Generator函数应运而生,它只是一个分段执行任务,通过状态指针next分布执行任务,但是流程管理不太方便(每个阶段何时执行不太明了),所以它只是一个中间产物。

      const gen = function* () {
        const f1 = yield this.login()
        const f2 = yield this.getInfo()
      };
      

      ES8中把async和await变得更加方便,它其实就是Generator的语法糖。async/await是写异步代码的新方式,以前的方法有回调函数Promise。相比于Promise,它更加简洁,并且处理错误、条件语句、获取中间值都更加方便。

      async function asyncFunc(params) {
        const result1 = await this.login()
        const result2 = await this.getInfo()
      }
      

      如果想进一步了解async的具体时间,可以参见阮一峰的博客es6.ruanyifeng.com/#docs/async

    • Object.entries()

      该方法会将某个对象的可枚举属性与值按照二维数组的方式返回。(如果目标对象是数组,则会将数组的下标作为键值返回)

      Object.entries({ one: 1, two: 2 })    //[['one', 1], ['two', 2]]
      Object.extries([1, 3])    //[['0', 1], ['1', 3]]
      
    • Object.values()

      它的工作原理和Object.entries()方法很像,但是它只返回键值对中的值,结果是一维数组

      Object.values({one: 1, two: 2})    // [1, 2]
      Object.values({3: 'a', 1: 'b', 2: 'c'}) // ['b', 'c', 'a'] 
      Object.extries([1, 3])     //[1, 3]
      
    • 字符串填充padStart()、padEnd()

      ES8提供了新的字符串填充方法,该方法可以使得字符串达到固定长度。它有两个参数,字符串目标长度和填充内容。

      'react'.padStart(10, 'm')      //'mmmmmreact'
      'react'.padEnd(10, 'm')       //' reactmmmmm'
      'react'.padStart(3, 'm')     // 'vue'
      

    相关文章

      网友评论

        本文标题:ES6/ES7/ES8常用特性和新特性

        本文链接:https://www.haomeiwen.com/subject/jotyaftx.html