ES6語(yǔ)法

一、let和const

es6之前有兩個(gè)作用域:全局作用域、函數(shù)作用域
es6新增加了塊作用域,也就是{}包起來(lái)的代碼

function test() {
    for (let i=1;i<3;i++){
        console.log(i);
    }
    console.log(i);//error: i is not defined
}

為什么報(bào)錯(cuò)?因?yàn)閑s6強(qiáng)制開(kāi)啟了嚴(yán)格模式,變量未聲明不能引用

let a=3;
let a=4;

報(bào)錯(cuò),不能重復(fù)聲明!

const PI=3.14;

定義常量,常量不能修改!也是有塊作用域的!并且,聲明的時(shí)候必須賦值!

const PI=3.14,
      k={
        a:1
      };
k.b=3;
console.log(PI,k);

可以輸出。是因?yàn)閗是對(duì)象,是引用類型,返回的是對(duì)象存儲(chǔ)內(nèi)存的指針,發(fā)生了修改也可以輸出。
const和let的唯一區(qū)別就是,const不可以被更改,所以當(dāng)聲明變量的時(shí)候,尤其是在聲明容易被更改的全局變量的時(shí)候,盡量使用const。

  • 更好的代碼語(yǔ)義化,一眼看到就是常量。
  • 另一個(gè)原因是因?yàn)镴avaScript 編譯器對(duì)const的優(yōu)化要比let好,多使用const,有利于提高程序的運(yùn)行效率。
  • 所有的函數(shù)都應(yīng)該設(shè)置為常量。

二、解構(gòu)賦值

解構(gòu)賦值的分類:數(shù)組結(jié)構(gòu)賦值(左右都是數(shù)組)、對(duì)象結(jié)構(gòu)賦值(左右都是對(duì)象)、字符串結(jié)構(gòu)賦值(左數(shù)組、右字符串)、布爾值結(jié)構(gòu)賦值、函數(shù)參數(shù)解構(gòu)賦值(數(shù)組解構(gòu)賦值在函數(shù)上的引用)、數(shù)值解構(gòu)賦值

{
    let a,b,rest;
    [a, b]=[1,2];
    console.log(a);//1
    console.log(b);//2
}
{
    let a,b,rest;
    [a, b, ...rest]=[1,2,3,4,5,6];
    console.log(a, b, rest);//1 2 [3,4,5,6]
}
{
    let a,b;
    ({a, b}={a:1,b:2});
    console.log(a, b);//1,2
}
{
    let a,b,c,rest;
    [a, b,c = 3]=[1,2];
    console.log(a, b, c);//1 2 3
}

如果c沒(méi)有賦值,找不到可以配對(duì)的值,c就是undifined。
適用場(chǎng)景:變量交換,選擇性獲取返回值

{
    let a=1;
    let b=2;
    [a, b]=[b,a];
    console.log(a, b);//2 1
}
{
    function f() {
       return [1,2];
    }
    let a,b;
    [a, b]=f();//1 2
}
{
    function f1() {
        return [1,2,3,4,5];
    }
    let a,b,c;
    [a, , ,b]=f1();
    console.log(a, b);//1 4
}
{
    function f1() {
        return [1,2,3,4,5];
    }
    let a,b,c;
    [a,...b]=f1();
    console.log(a, b);//1 [2,3,4,5]
}

上面這兩種也可以混合使用。
在用到數(shù)組成員對(duì)變量賦值時(shí),盡量使用解構(gòu)賦值。
對(duì)象的解構(gòu)賦值::

{
    let o={p:42,q:true};
    let {p,q}=o;
    console.log(p, q);//42 true
}
{
    let {a=10,b=5}={a:3};
    console.log(a, b);//3 5  a=10是默認(rèn)值,找不到匹配項(xiàng)時(shí)才=10
}

使用場(chǎng)景:

{
    let metaData={
        title: 'abc',
        test: [{
            title: 'test',
            desc: 'description'
        }]
    };
    let {title:esTitle,test:[{title:cnTitle}]} = metaData;
    console.log(esTitle,cnTitle);//abc test
}

函數(shù)的參數(shù)如果是對(duì)象的成員,優(yōu)先使用解構(gòu)賦值。
如果函數(shù)返回多個(gè)值,優(yōu)先使用對(duì)象的解構(gòu)賦值,而不是數(shù)組的解構(gòu)賦值。這樣便于以后添加返回值,以及更改返回值的順序。

三、正則擴(kuò)展

正則新增特性:u修飾符、y修飾符、s修飾符

{
    //es5
    let regex=new RegExp('xyz','i');
    let regex2=new RegExp(/xyz/i);//或者直接/xyz/i
    console.log(regex.test('xyz123'));//true
    console.log(regex2.test('xyz123'));//true

    //es6,參數(shù)可以下面這樣
    let regex3=new RegExp(/xyz/ig,'i');
    console.log(regex3.flags);//i 即第二個(gè)參數(shù)的修飾符會(huì)覆蓋前面正則表達(dá)式的修飾符
}
{
    //y修飾符 vs g修飾符
    let s='bbb_bb_b';
    let a1=/b+/g;
    let a2=/b+/y;
    console.log('one',a1.exec(s),a2.exec(s));//bbb bbb
    console.log('two',a1.exec(s),a2.exec(s));//bb null
    //相同點(diǎn):都是全局匹配
    //不同點(diǎn):g是上一次匹配的下一個(gè)字符開(kāi)始,即_,不強(qiáng)調(diào)在第一個(gè)字符就能匹配上
    //不同點(diǎn):y是上一次匹配的下一個(gè)字符開(kāi)始,即_,但是必須得在第一個(gè)字符就能匹配上
    console.log(a1.sticky,a2.sticky);//false true 是否開(kāi)啟y
}
{
    //u修飾符:unicode
    console.log('u-1',/^\uDB3D/.test('\uDB3D\uDC2A'));//u-1 true //\uDB3D\uDC2A當(dāng)成兩個(gè)字符
    console.log('u-2',/^\uDB3D/u.test('\uDB3D\uDC2A'));//u-2 false //\uDB3D\uDC2A當(dāng)成一個(gè)字符

    console.log(/\u{61}/.test('a'));//false
    console.log(/\u{61}/u.test('a'));//true

    console.log(`\u{20BB7}`);//unicode編碼大于FFFF,即大于兩個(gè)字節(jié)
    let s='??';
    console.log(/^.$/.test(s));//false
    console.log(/^.$/u.test(s));//true

    console.log('test',/??{2}/.test('????'));//test false
    console.log('test2',/??{2}/u.test('????'));//test2 true
    //總結(jié),大于兩個(gè)字節(jié)長(zhǎng)度的字符,要加u
    //但是仍然不能匹配換行符,回車(chē)符,行分隔符,段分隔符
    //如果要能匹配,使用s修飾符,但是s修飾符es6尚未實(shí)現(xiàn)
}

四、字符串?dāng)U展

安裝補(bǔ)丁庫(kù),處理兼容:npm install babel-polyfill --save-dev
需要引入兼容庫(kù):

import 'babel-polyfill';
{
    console.log('a','\u0061');//a a
    console.log('a','\u20BB7');//a ?7 超過(guò)了0xFFF,即兩個(gè)字節(jié),會(huì)被當(dāng)成兩個(gè)字符
    console.log('s',`\u{20BB7}`);//s ??
}
{
    let s='??';
    //es5
    console.log('length',s.length);//2 (碼字大于兩個(gè)字節(jié),當(dāng)四個(gè)字節(jié)處理,計(jì)算長(zhǎng)度的時(shí)候每?jī)蓚€(gè)字節(jié)算一個(gè)長(zhǎng)度)
    console.log('0',s.charAt(0));//0 亂碼
    console.log('0',s.charAt(2));//0 亂碼
    console.log('at0',s.charCodeAt(0));//at0 55362
    console.log('at1',s.charCodeAt(1));//at0 57271
    //es6
    let s1='??a';
    console.log('length',s1.length);//3
    console.log('code0',s1.codePointAt(0));//134071 取出4個(gè)字節(jié)
    console.log('code0',s1.codePointAt(0).toString(16));//20bb7
    console.log('code1',s1.codePointAt(1));//57271 取出后兩個(gè)字節(jié)
    console.log('code1',s1.codePointAt(2));//97 就是a
    //.toString(16)轉(zhuǎn)成16進(jìn)制
}
{
    //es5
    console.log(String.fromCharCode('0x20BB7'));//亂碼
    //es6
    console.log(String.fromCodePoint('0x20BB7'));//??
}
{
    let str='\u{20BB7}abc';
    for (let i=0;i<str.length;i++){
        console.log('es5',str[i]);//前兩個(gè)亂碼 a b c
    }
    for (let code of str){
        console.log('es6',code);//?? a b c
    }
}
{
    let str='string';
    console.log('includes',str.includes('r'));//true
    console.log('start',str.startsWith('str'));//true
    console.log('end',str.endsWith('ng'));//true
}
{
    let str='abc';
    //es5是用+
    console.log(str.repeat(2));//abcabc
}
//模板字符串
{
    let name='list';
    let info='hello world';
    let m=`i am ${name},${info}`;
    console.log(m);//i am list,hello world
    console.log('1'.padStart(2,'0'));//01
    console.log('1'.padEnd(2,'0'));//10
}
//標(biāo)簽?zāi)0澹悍胖肵SS攻擊,處理多語(yǔ)言
{
    let user={
        name: 'list',
        info: 'hello world'
    };
    console.log(abc`i am ${user.name},${user.info}`);
    function abc(s,v1,v2) {
        console.log(s, v1, v2);//["i am ", ",", "",] "list" "hello world"
        return s+v1+v2;//i am ,,,listhello world
    }
}
{
    console.log(String.raw`Hi\n${1-2}`);//Hi \n-1
    console.log('Hi\n${1+2}');//Hi 換行 ${1+2}
}

五、數(shù)值擴(kuò)展

{
    console.log(0b11110111);//247 0b二進(jìn)制(大小寫(xiě)均可)
    console.log(0o11111);//4681 0o八進(jìn)制(大小寫(xiě)均可)
}
{
    console.log('15',Number.isFinite(15));//true
    console.log('NaN',Number.isFinite(NaN));//false
    console.log('1/0',Number.isFinite(1/0));//false
    console.log('NaN',Number.isNaN(NaN));//true
    console.log('0',Number.isNaN(0));//false

    console.log('25',Number.isInteger(25));//true
    console.log('25.0',Number.isInteger(25.0));//true 25.0=25
    console.log('25.1',Number.isInteger(25.1));//false
    console.log('25.0',Number.isInteger('25.0'));//false

    console.log(Number.MAX_SAFE_INTEGER);
    console.log(Number.MIN_SAFE_INTEGER);
    console.log(Number.isSafeInteger(10));//true 是否位于上面兩個(gè)數(shù)的范圍內(nèi)
    console.log(Number.isSafeInteger('a'));//false

    //es5:Math.floor,Math.ceil
    console.log(4.1,Math.trunc(4.1));//4
    console.log(4.9,Math.trunc(4.9));//4

    console.log('-5',Math.sign(-5));//-1
    console.log('5',Math.sign(5));//1
    console.log('0',Math.sign(0));//0
    console.log('a',Math.sign('a'));//NaN

    //開(kāi)立方根
    console.log(Math.cbrt(-1));//-1
    console.log(Math.cbrt(8));//2
}

六、數(shù)組擴(kuò)展

{
    let arr=Array.of(3,4,7,9,11);
    console.log('arr',arr);//[3,4,7,9,11]
    console.log('arr',Array.of());//[]
}
{
    let p=document.querySelectorAll('p');
    let pArr=Array.from(p);//將上面的集合轉(zhuǎn)義成數(shù)組
    pArr.forEach(function (item) {
        console.log(item.textContent);
    });
    //map
    console.log(Array.from([1,3,5],function (item) {return item+2;}));//3 5 7
    //填充數(shù)組
    console.log('fill-7',[1,'a',undefined].fill(7));//[7,7,7]
    console.log('fill,pos',['a','b','c','d','e'].fill(7,1,3));//["a", 7, 7, "d", "e"] 1和3表示起始和截至位置,不包括位置3

    for (let index of ['1','c','ks'].keys()){
        console.log('keys',index);//0 1 2
    }
    for (let value of ['1','c','ks'].values()){
        console.log('values',value);//1 c ks
    }
    for (let [index,value] of ['1','c','ks'].entries()){
        console.log(index,value);
    }

    console.log([1,2,3,4,5].copyWithin(0,3,4));//[4,2,3,4,5] (從0開(kāi)始替換,從3開(kāi)始讀取,也就是第一個(gè)讀取的數(shù)是4,4是截至位置,也就是在位置4之前,因此只取4)

    console.log([1,2,3,4,5,6].find(function (item) {
        return item>3;//4,只找第一個(gè)
    }));
    console.log([1,2,3,4,5,6].findIndex(function (item) {
        return item>3;//3
    }));
    console.log('number',[1,2,NaN].includes(1));//true
    console.log('number',[1,2,NaN].includes(NaN));//true
}

使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組:const itemsCopy = [...items];

七、函數(shù)擴(kuò)展

{
    function test(x, y='world') {
        console.log('默認(rèn)值',x, y);
    }
    test();//undefined world

    let x='test';
    function test2(x,y=x) {
        console.log('作用域',x,y)
    }
    test2('kill');//kill kill
}
{//rest參數(shù)
    function test3(...arg) {//將輸入的參數(shù)都轉(zhuǎn)為數(shù)組
        for (let v of arg){
            console.log('rest',v);//a b c
        }
    }
    test3('a','b','c');

    //將數(shù)組轉(zhuǎn)成離散的值
    console.log(...[1,2,4]);//1 2 4
    console.log('a',...[1,2,4]);//a 1 2 4
}
{//箭頭函數(shù)
    let arrow = v => v+2;//v是參數(shù),v+2是返回值
    console.log('arrow',arrow(3));//5
    //無(wú)參數(shù)情況下
    let arrow2 = ()=> 2;
}
{//偽調(diào)用:函數(shù)的最后一句話是不是函數(shù)
    function tail(x) {
        console.log('tail',x);
    }
    function fx(x) {
        return tail(x);
    }
    fx(123);//tail 123
}

八、對(duì)象擴(kuò)展

這里的對(duì)象指Object對(duì)象

{
    // 簡(jiǎn)潔表達(dá)法
    let o=1;
    let k=2;
    let es5={
        o:o,
        k:k
    };
    let es6={
        o,
        k
    };
    console.log(es5,es6);//結(jié)果是一樣的

    let es5_mrthod={
        hello:function () {
            console.log('hello');
        }
    };
    let es6_method={
        hello(){
            console.log('hello');
        }
    };
    console.log(es5_mrthod,es6_method);//結(jié)果是一樣的

    //屬性表達(dá)式
    let a='b';
    let es5_obj={
        a: 'c'
    };
    let es6_obj={
        [a]:'c' //這里的a是變量,即b
    };
    console.log(es5_obj,es6_obj);

    //新增API
    console.log('字符串',Object.is('abc','abc'));//true 相當(dāng)于===
    console.log('數(shù)組',Object.is([],[]),[]===[]);//false false 引用地址不同
    //淺復(fù)制(只改引用地址)
    console.log('拷貝',Object.assign({a:'a'},{b:'b'}));//{a: "a", b:"b"}
    let test={k:123,o:456};
    for (let [key,value] of Object.entries(test)){
        console.log(key,value);
    }
}

不要聲明之后又給對(duì)象添加新屬性,如果一定非要加請(qǐng)使用Object.assign。

九、Symbol用法

Symbol的概念:用symbol聲明的變量,永遠(yuǎn)不相等。

{
    //聲明1
    let a1=Symbol();
    let a2=Symbol();
    console.log(a1===a2);//false
    //聲明2
    let a3=Symbol.for('a3');//'a3'會(huì)先檢查a3是否在全局注冊(cè)過(guò),如果是,返回該值
    let a4=Symbol.for('a3');
    console.log(a3===a4);//true
    //使用場(chǎng)景
    let a5=Symbol.for('abc');
    let obj={
        [a5]: '123',
        'abc': 345,
        'c': 456
    };
    console.log(a5,obj);//Symbol(abc) {abc: 345,c: 456, Symbol(abc): "123"}
    for (let [key,value] of Object.entries(obj)){
        console.log('let of',key,value);
    }
    //let of abc 345
    //let of c 456
    Object.getOwnPropertySymbols(obj).forEach(function (item) {
        console.log(obj[item]);//123
    });
    Reflect.ownKeys(obj).forEach(function (item) {
        console.log(item,obj[item]);//可以將所有的key-value值打印出來(lái)
    });
}

十、set-map數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu):set、weakset、map、weakmap
Object的key必須是字符串或者Symbol數(shù)據(jù)類型,而map的key可以是任意數(shù)據(jù)類型。
weakset與set支持的數(shù)據(jù)類型不同,weakset的元素只能是數(shù)據(jù)對(duì)象,且weakset中的對(duì)象是弱引用(地址引用),即不會(huì)檢測(cè)這個(gè)對(duì)象是否在其他地方用過(guò),也就意味著不會(huì)和垃圾回收機(jī)制掛鉤(不會(huì)檢測(cè)是否被回收)。

{//set
    let list=new Set();//沒(méi)有重復(fù)值
    list.add(5);
    list.add(7);
    console.log('size',list.size);//2

    let arr=[1,2,3,4,5];
    let list1=new Set(arr);
    console.log('size',list1.size);//5

    let list2=new Set();
    list2.add(1);
    list2.add(2);
    list2.add(1);
    console.log('size',list2.size);//2
    //重要應(yīng)用場(chǎng)景:去重
    let arr1=[1,2,3,1,2];
    let list3=new Set(arr1);
    console.log('unique',list3);//{1,2,3}
    let arr2=[1,2,3,1,"2"];
    let list4=new Set(arr2);
    console.log('unique',list4);//{1,2,3,"2"}

    let arr3=['add','delete','clear','has'];
    let list5=new Set(arr3);
    console.log(list5.has('add'));//true
    console.log('delete',list5.delete('add'),list5);//true {"delete","clear","has"}
    list5.clear();
    console.log(list5);//set(0)
    //key和value都是一樣的
    let list6=new Set(arr3);
    for (let key of list6.keys()){
        console.log('keys',key);
    }
    for (let value of list6.values()){
        console.log('values',value)
    }
    for (let value of list6.values()){
        console.log('values',value)
    }
    for (let [key,value] of list6.entries()){
        console.log(key,value)
    }
    list6.forEach(function (item) {
        console.log(item);
    });
}
{//weakset
    let weakList=new WeakSet();
    let arg={};
    weakList.add(arg);
    //weakList.add(2);//報(bào)錯(cuò)
    console.log(weakList);
    //無(wú)clear方法,無(wú)size屬性,不能遍歷
}
{//map
    let map=new Map();
    let arr=['123'];
    map.set(arr,459);
    console.log(map,map.get(arr));
    //第二種定義方式
    let map1=new Map([['a',123],['b',456]]);
    console.log(map1);//{"a"=>123,"b"=>456
    console.log('size',map1.size);
    console.log('delete',map.delete('a'),map);
    console.log('clear',map.clear(),map);
    //遍歷同set
}
{//weakmap
    let weakMap=new WeakMap();//接收對(duì)象必須是對(duì)象
    //無(wú)size對(duì)象,無(wú)clear方法,不能遍歷
}

十一、map-set與數(shù)組和對(duì)象的比較

{
    //map與數(shù)組的對(duì)比
    let map=new Map();
    let array=[];
    //增
    map.set('a',123);
    array.push({a:123});
    console.info('map-array',map, array);
    //查
    let map_exists=map.has('a');//true
    let array_exists=array.find(item =>item.a);//{a:123}
    //改
    map.set('a',2);
    array.forEach(item => item.a?item.a=2:'');
    //刪
    map.delete('a');
    let index=array.findIndex(item=>item.a);
    array.splice(index,1);
}
{
    //set和array的對(duì)比
    let set=new Set();
    let array=[];
    //增
    set.add({t:1});
    //查
    let set_exist=set.has({t:1});
    //改
    set.forEach(item=>item.t?item.t=2:'');
    //刪
    set.forEach(item=>item.t?set.delete(item):'');
}
{
    //map、set與object的區(qū)別
    let item={t:1};
    let map=new Map();
    let set=new Set();
    let obj={};
    //增
    map.set('t',1);
    set.add(item);
    obj['t']=1;
    //查
    console.info({
        map_exists: map.has('t'),
        set_exists: set.has(item),
        obj_exists: 't' in obj
    });
    //改
    map.set('t',2);
    item.t = 2;//set的改,引用類型
    obj['t']=2;
    //刪
    map.delete('t');
    set.delete(item);
    delete obj['t'];
}

如果只是簡(jiǎn)單的key: value結(jié)構(gòu),建議優(yōu)先使用Map,因?yàn)镸ap提供方便的遍歷機(jī)制。

十二、Proxy和Reflect

{
    //proxy:代理
    let obj={ //原始對(duì)象,存儲(chǔ)真實(shí)數(shù)據(jù)
        time: '2017-08-04',
        name: 'net',
        _r: 123
    };
    let monitor=new Proxy(obj,{//通過(guò)Proxy新生成一個(gè)對(duì)象
        //攔截對(duì)象屬性的讀取
        get(target,key){
            return target[key].replace('2017','2018');
        },
        //攔截對(duì)象屬性的設(shè)置
        set(target,key,value){
            if (key === 'name') {
                return target[key]=value;
            }else{
                return target;//不做任何操作
            }
        },
        //攔截key in Object 操作
        has(target,key){
            if (key === 'name'){
                return target[key];
            } else{
                return false;
            }
        },
        //攔截delete操作符
        deleteProperty(target,key){
            if (key.indexOf('_')>-1){
                delete target[key];
                return true;
            }else{
                return target[key];
            }
        },
        //攔截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertNames
        ownKeys(target){
            return Object.keys(target).filter(item=>item!='time');
        }
    });
    //用戶使用的是monitor
    console.log(monitor.time);
    monitor.time='2018';
    console.log(monitor.time);//沒(méi)有變化
    monitor.name = 'com';
    console.log(monitor.name);//com
    console.log('name' in monitor);//true
    delete monitor['time'];
    console.log(monitor);//未刪除
    delete monitor._r;
    console.log(monitor);//刪除
    console.log(Object.keys(monitor));//"name"
}
{
    //reflect:方法同proxy
    let obj={ //原始對(duì)象,存儲(chǔ)真實(shí)數(shù)據(jù)
        time: '2017-08-04',
        name: 'net',
        _r: 123
    };
    console.log(Reflect.get(obj,'time'));//2017-08-04
    Reflect.set(obj,'name','com');
    console.log(obj);//com
    console.log(Reflect.has(obj,'name'));//true
}
{
    //使用場(chǎng)景:數(shù)據(jù)類型的校驗(yàn)(與業(yè)務(wù)解耦的校驗(yàn)?zāi)K)
    function validator(target,validator) {
        return new Proxy(target,{
            _validator:validator,
            set(target,key,value,proxy){
                if (target.hasOwnProperty(key)){
                    let va=this._validator[key];
                    if (!!va[value]){
                        return Reflect.set(target,key, value,proxy);
                    }else{
                        throw Error(`不能設(shè)置${key}為${value}`);
                    }
                }else{
                    throw Error(`${key}不存在`);
                }
            }
        });
    }
    const personValidators={
        name(val){
            return typeof val === 'string';
        },
        age(val){
            return typeof val === 'number' && val>18;
        }
    };
    class Person{
        constructor(name,age){
            this.name=name;
            this.age=age;
            return validator(this,personValidators);
        }
    }
    const person=new Person('lilei',30);
    console.info(person);//Proxy{name:"lilei",age:30}
    person.name=48;//error:不能設(shè)置name為48
}

十三、類和對(duì)象

{
    //類的基本定義和生成實(shí)例
    class Parent{
        //es6中定義構(gòu)造函數(shù)
        constructor(name='com'){
            this.name=name;
        }
    }
    let v_parent=new Parent('net');
    console.info(v_parent);

    //繼承
    class Child extends Parent{

    }
    console.log(new Child());//{name:"com"}
    //繼承傳遞參數(shù),將參數(shù)傳遞給父類
    class Child2 extends Parent{
        constructor(name='child'){
            super(name);//super一定放在構(gòu)造函數(shù)的第一行
            this.type='child';
        }
    }
    console.log(new Child2());//{name:"child",type:"child"}

    //getter,setter
    class Parent2{
        constructor(name='com'){
            this.name=name;
        }
        get longName(){
            return 'long'+this.name;
        }
        set longName(value){
            this.name=value;
        }
    }
    let v_parent2=new Parent2();
    v_parent2.longName='net';
    console.log(v_parent2.longName);//longnet

    //靜態(tài)方法、靜態(tài)屬性
    class Parent3{
        constructor(name='com'){
            this.name=name;
        }
        static tell(){//靜態(tài)方法
            console.log('tell');
        }
    }
    Parent.type = 'test';//這個(gè)就是靜態(tài)屬性
    Parent3.tell();

}

十四、Promise

Promise是異步編程的一種解決方案。

{
    //使用回調(diào)的方式
    //缺點(diǎn):如果是按順序執(zhí)行a,b,c...,代碼的寫(xiě)法會(huì)非常復(fù)雜,代碼的復(fù)雜影響后期的維護(hù)
    let ajax=function (callback) {
        console.log('執(zhí)行');
        setTimeout(function () {
            callback&&callback.call();
        },1000);
    };
    ajax(function () {
        console.log('timeout1');
    });

    //使用promise解決方案
    let ajax1=function () {
        console.log('執(zhí)行1');
        return new Promise(function (resolve,reject) {
            //resolve:要執(zhí)行下一步的操作
            //reject:要中斷當(dāng)前的操作
            setTimeout(function () {
                resolve();
            },1000);
        });
    };
    ajax1().then(function () {
        console.log('promise','timeout2');
        return new Promise(function (resolve,reject) {
           setTimeout(function () {
               resolve();
           },1000);
        });
    })
        .then(function () {
        console.log('promise','timeout3');
    });
}
{//捕獲錯(cuò)誤
    let ajax=function (num) {
        console.log('執(zhí)行2');
        return new Promise(function (resolve,reject) {
            if (num>5){
                resolve();
            }else {
                throw new Error('出錯(cuò)了');
            }
        });
    };
    ajax(2).then(function () {
        console.log(6);
    }).catch(function (err) {
        console.log(err);
    });
}
{//應(yīng)用場(chǎng)景
    //所有圖片加載完再加載頁(yè)面
    function loadImg(src) {
        return new Promise((resolve, reject)=>{
            let img=document.createElement('img');
            img.src=src;
            img.onload=function () {//圖片加載完成
                resolve(img);
            };
            img.onerror = function () {
                reject(err);
            };
        });
    }
    function showImgs(imgs) {
        imgs.forEach(function (img) {
            document.body.appendChild(img);
        });
    }
    Promise.all([
        loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
        loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
        loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png')
    ]).then(showImgs);
}
{//應(yīng)用場(chǎng)景
    //有一個(gè)圖片加載完就添加到頁(yè)面
    function loadImg(src) {
        return new Promise((resolve, reject)=>{
            let img=document.createElement('img');
            img.src=src;
            img.onload=function () {//圖片加載完成
                resolve(img);
            };
            img.onerror = function () {
                reject(err);
            };
        });
    }
    function showImgs(img) {
        let p=document.createElement('p');
        p.appendChild(img);
        document.body.appendChild(p);
    }
    Promise.race([
        loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
        loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
        loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png')
    ]).then(showImgs);
}

十五、Iterator和for...of循環(huán)

{
    let arr=['hello','world'];
    let map=arr[Symbol.iterator]();
    console.log(map.next());//{value:"hello",done:false}
    console.log(map.next());//{value:"world",done:false}
    console.log(map.next());//{value:undefined,done:false}
}
{
    let obj={
        start: [1,3,2],
        end: [7,9,8],
        [Symbol.iterator](){
            let self=this;
            let index=0;
            let arr=self.start.concat(self.end);
            let len=arr.length;
            return{
                next(){//寫(xiě)遍歷過(guò)程
                    if (index<len){
                        return{
                            value:arr[index++],
                            done:false
                        }
                    }else{
                        return{
                            value:arr[index++],
                            done: true
                        }
                    }
                }
            }
        }
    };
    for (let key of obj){
        console.log(key);//1 3 2 7 9 8
    }
}
{//for...of
    let arr=['hello','world'];
    for (let value of arr){
        console.log(value);//hello world
    }
}

十六、Genertor

Genertor也是異步編程的一種解決方案,但是相對(duì)promise更高級(jí)一點(diǎn)。

{
    let state=function* (){
        while(1){
            yield 'A';
            yield 'B';
            yield 'C';
        }
    };
    let status=state();
    console.log(status.next());//A done:false
    console.log(status.next());//B done:false
    console.log(status.next());//C done:false
    console.log(status.next());//A done:false
    console.log(status.next());//B done:false
}
{//應(yīng)用場(chǎng)景:抽獎(jiǎng)
    let draw=function (count) {
        //具體抽獎(jiǎng)邏輯略
        console.info(`剩余${count}次`);
    };
    let residue=function* (count) {
        while(count>0){
            count--;
            yield draw(count);
        }
    };
    let start=residue(5);
    let btn=document.createElement('button');
    btn.id='start';
    btn.textContent='抽獎(jiǎng)';
    document.body.appendChild(btn);
    document.getElementById('start').addEventListener('click',function () {
        start.next();
    },false);
}
{//應(yīng)用場(chǎng)景:定期向服務(wù)端獲取數(shù)據(jù),使用長(zhǎng)輪詢
    let ajax=function* () {
        yield new Promise(function (resolve,reject) {
            setTimeout(function () {
                resolve({code:0})
            },200);
        })
    };
    let pull=function () {
        let generator=new ajax();
        let step=generator.next();
        step.value.then(function (d) {//step.value就是promise實(shí)例
            if (d.code!=0) {//表示數(shù)據(jù)未更新
                setTimeout(function () {
                    console.log('wait');
                    pull();
                },1000);
            }else{
                console.log(d);
            }
        });
    };
    pull();
}

十七、Decorators

修飾器:一個(gè)函數(shù),用來(lái)修改類的行為。
需要安裝插件:npm install babel-plugin-transform-decorators-legacy --save-dev
.babelrc:"plugins":["transform-decorators-legacy"]

{
    let readonly=function (target,name,descriptor) {
        //target:修改類本身
        //name:修改屬性名稱
        //descriptor:屬性的描述對(duì)象
        descriptor.writable=false;
        return descriptor;
    };
    class Test{
        @readonly //修飾器
        time(){
            return '2017-03-11';
        }
    }
    let test=new Test();
    console.log(test.time());//2017-03-11
    // test.time=function(){
    //     console.log('reset');//error: Cannot assign to read only property 'time' of object
    // };

    //在類外面操作必須在class前
    let typename=function (target,name,descriptor) {
        target.myname='hello';//靜態(tài)屬性
    };
    @typename
    class Test2{

    }
    console.log(Test2.myname);//hello

    //第三方庫(kù)修飾器的js庫(kù):core-decorators(npm install core-decorators)
}
{//應(yīng)用場(chǎng)景:埋點(diǎn)
    //將埋點(diǎn)系統(tǒng)從業(yè)務(wù)邏輯中拆離
    let log=(type)=>{
        return function (target,name,descriptor) {
            let src_method=descriptor.value;
            descriptor.value=(...arg)=>{
                src_method.apply(target,arg);
                console.info(`log ${type}`);
            }
        }
    };
    class AD{
        @log('show')
        show(){
            console.log('ad is show');
        }
        @log('type')
        click(){
            console.log('ad is click');
        }
    }
    let ad=new AD();
    ad.show();//ad is show   log show
    ad.click();//ad is click  log type
}

十八、模塊化

ES6的模塊化語(yǔ)法:引入import、導(dǎo)出export
導(dǎo)出:

export let A=123;
export function test() {
    console.log('test');
}
export class Hello {
    test(){
        console.log('class');
    }
}

導(dǎo)入:

import {A,test,Hello} from "./class/lesson17";
console.log(A, test, Hello);

可以只導(dǎo)入部分變量:

import {A} from "./class/lesson17";
console.log(A);

起別名:

import * as lesson from "./class/lesson17";
console.log(lesson.A);

不給導(dǎo)出數(shù)據(jù)起名字(推薦):

let A=123;
function test() {
    console.log('test');
}
class Hello {
    test(){
        console.log('class');
    }
}
export default {
    A,
    test,
    Hello
}

導(dǎo)入:

import lesson from "./class/lesson17";
console.log(lesson.A);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 以下內(nèi)容是我在學(xué)習(xí)和研究ES6時(shí),對(duì)ES6的特性、重點(diǎn)和注意事項(xiàng)的提取、精練和總結(jié),可以做為ES6特性的字典;在本...
    科研者閱讀 3,282評(píng)論 2 9
  • [TOC] 參考阮一峰的ECMAScript 6 入門(mén)參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,915評(píng)論 0 1
  • 最近在做畢業(yè)設(shè)計(jì),其中用到了一些 ES6 的語(yǔ)法,比如模塊的輸出引入,箭頭函數(shù),對(duì)象字面量的簡(jiǎn)寫(xiě),等等。所性順便就...
    小烏龜變王八閱讀 515評(píng)論 0 0
  • 作用域的概念 es2015函數(shù)作用域全局作用域 es6函數(shù)作用域全局作用域塊作用域(新增,標(biāo)識(shí):有大括號(hào)包圍的)P...
    lincimy閱讀 2,791評(píng)論 2 1
  • 你說(shuō)你熱愛(ài)春天和原野,后來(lái)你離開(kāi)了再熟悉不過(guò)的生活,你戴了一塊兒表,背了一個(gè)雙肩包,那個(gè)背影定格在我們這群朋友的記...
    面壁yang閱讀 239評(píng)論 0 2

友情鏈接更多精彩內(nèi)容