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…

相關文章
相關標籤/搜索