es7/es8新特性

es7

1.Array.prototype.includes()

1.基本用法: ['a', 'b', 'c'].includes('a')     // true
        2.接收俩个参数:要搜索的值和搜索的开始索引
                    ['a', 'b', 'c', 'd'].includes('b', 1)      // true
        3.与ES6中的indexOf()比较--有些时候是等效的
                    ['a', 'b', 'c'].includes('a')          //true
                    ['a', 'b', 'c'].indexOf('a') > -1      //true
                在判断 +0 与 -0 时,被认为是相同的。
                    [1, +0, 3, 4].includes(-0)    //true
                    [1, +0, 3, 4].indexOf(-0)     //1
复制代码

2.求幂运算符

3 ** 2  //9  效果同  Math.pow(3, 2) //9
    var b = 3;  b **= 2; console.log(b); //9
复制代码

es8

1.async await

异步函数async function()
    所以提出了ES6的Promise,将回调函数的嵌套,改成了链式调用:
    var promise = new Promise((resolve, reject) => {
      this.login(resolve);
    })
    .then(() => {
      this.getInfo()
    })
    .catch(() => {
      console.log('Error')
    })
1.2声明方式
    异步函数存在如下四种使用形式:
    
    函数声明: async function foo() {}
    
    函数表达式: const foo = async function() {}
    
    对象的方式: let obj = { async foo() {} }
    
    箭头函数: const foo = async () => {}

1.3支持返回Promise和同步的值
    //async await
    //返回Promise
    let timer = async function timer() {
        return new Promise((reslove, reject) => {
            setTimeout(() => {
                reslove('a');
            }, 1000);
        })
    }
    timer().then(result => {
        console.log(result);
    }).catch(err => {
        console.log(err.message);
    })

    //返回同步的值
    let sayHello = async function sayHello() {
        let hi = 'hello world'//等同于return Promise.resolve(hi);
        return hi
    }
    sayHello().then(res => {
        console.log(res)
    }).catch(err => {
        console.log(err.message);
    })
1.4对异常的处理
    首先来看下Promise中对异常的处理
        1.使用reject
            let promise = new Promise((reslove, reject) => {
              setTimeout(() => {
                reject('promise使用reject抛出异常')  
              }, 1000)
            })
            promise().then(res => {
              console.log(res)
            })
            .catch(err => {
              console.log(err)     //'promise使用reject抛出异常'
            })
        2.使用new Error()
            let promise = new Promise((reslove, reject) => {
                throw new Error('promise使用Error抛出异常') //使用throw异常不支持放在定时器中
            })
            promise().then(res => {
              console.log(res)
            })
            .catch(err => {
              console.log(err.message)     //'promise使用Error抛出异常'
            })
        3.reject一个new Error()
            let promise = new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject(new Error('promise抛出异常'));
                }, 1000);
            })
        
            promise.then(res => {
                console.log(res);
            })
            .catch(err => {
                console.log(err.message);  //'promise抛出异常'
            })
                    
    async对异常的处理也能够直接用.catch()捕捉到
         //async抛出异常
        let sayHi = async sayHi => {
                throw new Error('async抛出异常');
        }
        sayHi().then(res => {
            console.log(res);
        })
        .catch(err => {
            console.log(err.message);
        })
    和Promise链的对比:
        咱们的async函数中能够包含多个异步操做,其异常和Promise链有相同之处,若是有一个Promise被reject()那么后面的将不会再进行。
        let count = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('promise故意抛出异常')
                }, 1000);
            })
        }
        let list = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve([1, 2, 3])
                }, 1000);
            })
        }
    
        let getList = async () => {
            let c = await count()
            console.log('async')    //此段代码并无执行
            let l = await list()
            return { count: c, list: l }
        }
        console.time('start');
        getList().then(res => {
            console.log(res)
        })
        .catch(err => {
            console.timeEnd('start')
            console.log(err)
        })
        
        //start: 1000.81494140625ms
        //promise故意抛出异常
1.5并行
    上面的案例中,async采用的是串行处理
    count()和list()是有前后顺序的
    如果请求的两个异步操做没有关联和前后顺序性能够采用下面的作法
        let res = await Promise.all([count(), list()])
        return res
        
        //res的结果为
        //[ 100, [ 1, 2, 3 ] ]
    案例详情为:
        let count = ()=>{
            return new Promise((resolve,reject) => {
                setTimeout(()=>{
                    resolve(100);
                },500);
            });
        }
        
        let list = ()=>{
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve([1,2,3]);
                },500);
            });
        }
        
        let getList = async ()=>{
            let result = await Promise.all([count(),list()]);
            return result;
        }
        console.time('begin');
        getList().then(result => {
            console.timeEnd('begin');  //begin: 505.557ms
            console.log(result);       //[ 100, [ 1, 2, 3 ] ]
        }).catch(err => {
            console.timeEnd('begin');
            console.log(err);
        });
        咱们将count()和list()使用Promise.all()“同时”执行,这里count()和list()能够看做是“并行”执行的,所耗时间将是两个异步操做中耗时最长的耗时。最后获得的结果是两个操做的结果组成的数组。 
1.6与Generator的关系
    ES6中Generator函数的用法:
        function* getList() {
            const c = yield count()
            const l = yield list()
            return 'end'
        }
        var gl = getList()
        console.log(gl.next()) // {value: Promise, done: false}
        console.log(gl.next()) // {value: Promise, done: false}
        console.log(gl.next()) // {value: 'end', done: true}
    ES8引入了async函数,使得异步操做变得更加方便
        let getList = async () => {
          const c = await count()
          const l = await list()
        }
复制代码

2.Object.entries()

2.1做用
    做用:将一个对象中可枚举属性的键名和键值按照二维数组的方式返回。 若对象是数组,则会将数组的下标做为键值返回
    Object.entries({ one: 1, two: 2 })    //[['one', 1], ['two', 2]]
    Object.entries([1, 2])             //[['0', 1], ['1', 2]]
2.2要点
    1.如果键名是Symbol,编译时会被自动忽略
        Object.entries({[Symbol()]:1, two: 2})  //[['two', 2]]
    2.entries()返回的数组顺序和for循环同样,即若是对象的key值是数字,则返回值会对key值进行排序,返回的是排序后的结果
        Object.entries({ 3: 'a', 4: 'b', 1: 'c' })    //[['1', 'c'], ['3', 'a'], ['4', 'b']]
    3.利用Object.entries()建立一个真正的Map
        var obj = { foo: 'bar', baz: 42 };
        var map1 = new Map([['foo', 'bar'], ['baz', 42]]); //本来的建立方式
        var map2 = new Map(Object.entries(obj));    //等同于map1
        console.log(map1);// Map { foo: "bar", baz: 42 }
        console.log(map2);// Map { foo: "bar", baz: 42 }
2.3自定义Object.entries()
    Object.entries的原理其实就是将对象中的键名和值分别取出来而后推动同一个数组中
         //自定义entries()
        var obj = { foo: 'bar', baz: 42 };
        function myEntries(obj) {
            var arr = []
            for (var key of Object.keys(obj)) {
                arr.push([key, obj[key]])
            }
            return arr
        }
        console.log(myEntries(obj))
        
        //Generator版本
        function* genEntryies(obj) {
            for (let key of Object.keys(obj)) {
                yield [key, obj[key]]
            }
        }
        var entryArr = genEntryies(obj);
        console.log(entryArr.next().value) //["foo", "bar"]
        console.log(entryArr.next().value) //["baz", 42]
复制代码

3.Object.values()

3.1做用
    做用:只返回本身的键值对中属性的值。它返回的数组顺序,也跟Object.entries()保持一致
        Object.values({ one: 1, two: 2 })            //[1, 2]
        Object.values({ 3: 'a', 4: 'b', 1: 'c' })    //['c', 'a', 'b']
3.2与Object.keys()比较
    ES6中的Object.keys()返回的是键名
        var obj = { foo: 'bar', baz: 42 };
        console.log(Object.keys(obj)) //["foo", "baz"]
        console.log(Object.values(obj)) //["bar", 42]
        
        //Object.keys()的做用就相似于for...in
        function myKeys() {
            let keyArr = []
            for (let key in obj1) {
                keyArr.push(key)
                console.log(key)
            }
            return keyArr
        }
        console.log(myKeys(obj1)) //["foo", "baz"]
3.3entries()、values()总结
    var obj = { foo: 'bar', baz: 42 };
    console.log(Object.keys(obj)) //["foo", "baz"]
    console.log(Object.values(obj)) //["bar", 42]
    console.log(Object.entries(obj)) //[["foo", "bar"], ["baz", 42]]
复制代码

4.字符串填充

4.1padStart()和padEnd()
    字符串填充padStart()和padEnd() String.padStart(targetLength, padding)  参数:字符串目标长度和填充字段
    'Vue'.padStart(10)           //'       Vue'
    'React'.padStart(10)         //'     React'
    'JavaScript'.padStart(10)    //'JavaScript'
4.2要点
    填充函数只有在字符长度小于目标长度时才有效,并且目标长度若是小于字符串自己长度时,字符串也不会作截断处理,只会原样输出
    'Vue'.padEnd(10, '_*')           //'Vue_*_*_*_'
    'React'.padEnd(10, 'Hello')      //'ReactHello'
    'JavaScript'.padEnd(10, 'Hi')    //'JavaScript'
    'JavaScript'.padEnd(8, 'Hi')     //'JavaScript'
复制代码

5.Object.getOwnPropertyDescriptors()

5.1做用
    该方法会返回目标对象中全部属性的属性描述符,该属性必须是对象本身定义的,不能是从原型链继承来的。
     var obj = {
            id:  1,
            name: '霖呆呆',
            get gender() {
                console.log('gender')
            },
            set grad(d) {
                console.log(d)
            }
        }
        console.log(Object.getOwnPropertyDescriptors(obj))
     //输出   
    {
      gender: {
        configurable: true,
        enumerable: true,
        get: f gender(),
        set: undefined
      },
      grade: {
        configurable: true,
        enumerable: true,
        get: undefined,
        set: f grade(g)
      },
      id: {
        configurable: true,
        enumerable: true,
        value: 1,
        writable: true
      },
      name: {
        configurable: true,
        enumerable: true,
        value: '霖呆呆',
        writable: true
      }
    }
    第二个参数,用于指定属性的属性描述符
    Object.getOwnPropertyDescriptors(obj, 'id')
    //输出结果应该为
    {
      id: {
        configurable: true,
        enumerable: true,
        value: 1,
        writable: true
      }
    }
5.2与getOwnPropertyDescriptor()比较
    ES6中也有一个返回目标对象可枚举属性的方法
    var obj = {
        id: 1,
        name: '霖呆呆',
        get gender() {
            console.log('gender')
        },
        set grad(d) {
            console.log(d)
        }
    }
    console.log(Object.getOwnPropertyDescriptor(obj, 'id'))
            
    //输出结果
     {
      id: {
        configurable: true,
        enumerable: true,
        value: 1,
        writable: true
      }
    }
    二者的区别:一个是只返回知道属性名的描述对象,一个返回目标对象全部自身属性的描述对象
5.3自定义该方法
    function myDescriptors(obj) {
        let descriptors = {}
        for (let key in obj) {
            descriptors[key] = Object.getOwnPropertyDescriptor(obj, key)
        }
        return descriptors
    }
    console.log(myDescriptors(obj))
    //返回的结果和该方法同样
    //其中上面自定义方法的for...in也能够换成,效果也是同样的
    for (let key of Object.keys(obj)) {
        descriptors[key] = Object.getOwnPropertyDescriptor(obj, key)
    }
复制代码

6.函数参数支持尾部逗号

let foo = function (
                a,
                b,
                c,
            ) {
                console.log('a:', a)
                console.log('b:', b)
                console.log('c:', c)
            }
            foo(1, 3, 4, )

            //输出结果为:
            a: 1
            b: 3
            c: 4
复制代码

7.修饰器Decorator

定义一个函数,在调用这个函数时,可以执行一些其余额外操做 以下代码,定义doSometing(),在调用它时再执行其余代码
function doSometing(name) {
        console.log('Hello' + name)
    }
    function myDecorator(fn) {
        return function() {
            console.log('start')
            const res = fn.apply(this, arguments)
            console.log('end')
            return res
        }
    }
    const wrapped = myDecorator(doSometing)
    doSometing('lindaidai')
    //Hellowlindaidai
    
    wrapped('lindaidai')
    //start 
    //Hellowlindaidai
    //end
能够看到上面的操做:其实就是一个函数包装成另外一个函数,这样的方式咱们称之为“修饰器”
    @addSkill
    class Person { }
    
    function addSkill(target) {
        target.say = "hello world";
    }
    console.log(Person['say']) //'hello world'
若是想使用Person这个类建立出来的对象也能附加上一些属性,能够在目标对象的原型对象中进行添加:
    @addSkill
    class Person { }
    
    function addSkill(target) {
        target.say = "hello world"; //直接添加到类中
        target.prototype.eat = "apple"; //添加到类的原型对象中
    }
    var personOne = new Person()
    
    console.log(Person['say']) // 'hello world'
    console.log(personOne['eat']) // 'apple'
    **上面案例中的@addSkill其实就是一个最简单的修饰器。**
    固然,若是你将上面案例中的代码复制到你html文件中,会发现它并不能如愿的执行:那是由于decorator是es7提供的方法,在浏览器中是没法直接运行的,若是你想要使用它,咱们须要提早作一些准备,对它进行编译。
7.2 快速使用
    网上使用Decorator的教材有不少,大多都是要须要使用插件来让浏览器支持Decorator。这里长话短说,贴上一个最精简的使用教程:
    1.建立一个名为:Decorator的文件夹
    2.在文件夹目录下执行命令行:npm i babel-plugin-transform-decorators-legacy babel-register --save-dev
        此时文件夹下会出现俩个文件: node_modules 依赖文件夹和package.json-lock.json
    3.建立文件 complie.js
        require('babel-register')({
            plugins: ['transform-decorators-legacy']
        });
        require("./app.js")
    4.建立文件 app.js
        @addSkill
            class Person { }
            function addSkill(target) {
                target.say = "hello world";
            }
            console.log(Person.say)   //'hello world'
    5.在根目录下执行指令:
        node complie.js
        此时能够看到命令行中打印出了 hello world
        
        简单介绍下上面步骤的原理:
            第二步中使用了俩个基础插件:
                transform-decorators-legacy:
                //是第三方插件,用于支持decorators
                babel-register:
                //用于接入node api
            第三步、第四步建立的俩个文件
                complie.js  //用来编译app
                app.js   //使用了装饰器的js文件
            第五步:
                原理:
                    1,node执行complie.js文件;
                    2,complie文件改写了node的require方法;
                    3,complie在引用app.js,使用了新的require方法;
                    4,app.js在加载过程当中被编译,并执行。
7.3 类修饰器
    直接做用在类上面的修饰器,咱们能够称之为类修饰器
    如上面案例中的@addSkill就是一个类修饰器,它修改了Person这个类的行为,为它加上了静态属性say。
    addSkill函数的参数target是Person这个类自己。
    1.修饰器的执行原理基本就是这样:
        @decorator
        class A {}
        // 等同于
        class A {}
        A = decorator(A) || A;
        换句话说,类修饰器是一个对类进行处理的函数。
        固然若是你想要有多个参数也是能够的,咱们能够在修饰器外面再封装一层函数
        @addSkill("hello world")
        class Person { }
        function addSkill(text) {
            return function(target) {
                target.say = text;
            }
        }
        console.log(Person.say)  //'hello world'
复制代码

www.jianshu.com/p/13c5d0024…

相关文章
相关标签/搜索