【嘔心整理】ES6入門基礎(chǔ),包含運(yùn)行代碼

ES6入門基礎(chǔ)

推薦書籍 《ECMAScript 6 入門》:http://es6.ruanyifeng.com/

碼云倉庫代碼(歡迎Start)

碼云倉庫代碼-https://gitee.com/hongjunyong/es6-imooc-lottery

1、為什么要學(xué)習(xí)ES6

detail.png

1.1、對(duì)象拷貝

copy.png

1.2、參數(shù)傳遞

data.png

1.3、更多特性:解構(gòu)賦值、箭頭函數(shù)、set和map、異步操作、類與對(duì)象、模塊化

2、項(xiàng)目構(gòu)建(略)

    // -e要使用ejs模版引擎 .當(dāng)前目錄執(zhí)行
    express -e .
express.png
    // 安裝依賴:npm install
    
    npm install gulp gulp-if gulp-concat webpack webpack-stream vinyl-named gulp-livereload gulp-plumber gulp-rename gulp-uglify gulp-util y
    args --save-dev
    
    項(xiàng)目運(yùn)行 gulp --watch

3、ES6語法

3.1、let const命令(案例:lesson1-let-const.js)

3.1.1、let的生命周期

    // i在for循環(huán)外面依舊有效
    for(var i=1;i<3;i++){
        console.log(i);
    }
    console.log(i);

    // i只有在for循環(huán)里面有效,出了括號(hào)生命周期結(jié)束
    for(let i=1;i<3;i++){
        console.log(i);
    }
    console.log(i);
let.png

3.1.2、let變量不能重復(fù)定義

    錯(cuò)誤:
        let a = 1;
        let a = 2;

3.1.3、const常量不能修改,對(duì)象可以修改(指針),且聲明的時(shí)候必須賦值

    const常量不能修改
        錯(cuò)誤:
            const a = 1;
            a = 2;

    對(duì)象可以修改
        正確:
            const k = {
                a:1
            }
            k.b = 3;
    
    聲明的時(shí)候必須賦值
        錯(cuò)誤:
            const a;
            a = 1;
        正確:
            const a = 1;

3.1.4、es6開啟嚴(yán)格模式('use strict')

3.1.4.1 不允許使用未聲明的變量
    "use strict";
    x = 3.14;                // 報(bào)錯(cuò) (x 未定義)
3.1.4.2 不允許使用未聲明的變量(對(duì)象也是一個(gè)變量)
    "use strict";
    x = { p1: 10,  p2: 20 };      // 報(bào)錯(cuò) (x 未定義)
3.1.4.3 不允許刪除變量或?qū)ο?/h5>
    "use strict";
    var x = 3.14;
    delete x;                // 報(bào)錯(cuò)
3.1.4.4 不允許刪除函數(shù)
    "use strict";
    function x(p1, p2) {}; 
    delete x;                // 報(bào)錯(cuò)
3.1.4.5 不允許變量重名
    "use strict";
    function x(p1, p1) {};   // 報(bào)錯(cuò)
3.1.4.6 不允許使用八進(jìn)制
    "use strict";
    var x = 010;             // 報(bào)錯(cuò)
3.1.4.7 不允許使用轉(zhuǎn)義字符
    "use strict";
    var x = \010;            // 報(bào)錯(cuò)
3.1.4.8 不允許對(duì)只讀屬性賦值
    "use strict";
    var obj = {};
    Object.defineProperty(obj, "x", {value:1, writable:false});
    console.log(obj);        // 輸出{x: 1}
    obj.x = 3.14;            // 報(bào)錯(cuò)
3.1.4.9 不允許對(duì)一個(gè)使用getter方法讀取的屬性進(jìn)行賦值
    "use strict";
    var obj = {get x() {return 0} };
    obj.x = 3.14;            // 報(bào)錯(cuò)
3.1.4.10 不允許刪除一個(gè)不允許刪除的屬性
    "use strict";
    delete Object.prototype; // 報(bào)錯(cuò)
3.1.4.11 變量名不能使用 "eval" 字符串
    "use strict";
    var eval = 3.14;         // 報(bào)錯(cuò)
3.1.4.12 變量名不能使用 "arguments" 字符串:
    "use strict";
    var arguments = 3.14;    // 報(bào)錯(cuò)
3.1.4.13 全局的'use strict',函數(shù)內(nèi)的變量也聲明
    "use strict";
    myFunction();
    
    function myFunction() {
        y = 3.14;   // 報(bào)錯(cuò) (y 未定義)
    }
3.1.4.14 函數(shù)內(nèi)部聲明是局部作用域 (只在函數(shù)內(nèi)使用嚴(yán)格模式):
    x = 3.14;       // 不報(bào)錯(cuò) 
    myFunction();
    
    function myFunction() {
       "use strict";
        y = 3.14;   // 報(bào)錯(cuò) (y 未定義)
    }
3.1.4.4 為什么使用嚴(yán)格模式:
消除Javascript語法的一些不合理、不嚴(yán)謹(jǐn)之處,減少一些怪異行為;
消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全;
提高編譯器效率,增加運(yùn)行速度;
為未來新版本的Javascript做好鋪墊。
"嚴(yán)格模式"體現(xiàn)了Javascript更合理、更安全、更嚴(yán)謹(jǐn)?shù)陌l(fā)展方向,包括IE 10在內(nèi)的主流瀏覽器,都已經(jīng)支持它,許多大項(xiàng)目已經(jīng)開始全面擁抱它。

3.2、解構(gòu)賦值(案例:lesson2-jiegou.js)

解構(gòu)賦值的分類:數(shù)組解構(gòu)賦值、對(duì)象解構(gòu)賦值、字符串解構(gòu)賦值、布爾值解構(gòu)賦值、函數(shù)參數(shù)解構(gòu)賦值、數(shù)值解構(gòu)賦值

3.2.1、數(shù)組解構(gòu)賦值

    // 塊作用域:變量的重復(fù)聲明,用塊包起來就不會(huì)出現(xiàn)問題
    {}
    
    {
        let a, b, rest;
        [a, b] = [1, 2];
        // 輸出1 2
        console.log(a, b);
    }
    
    {
        let a, b, rest;
        [a,b,...rest]=[1,2,3,4,5,6]
        // 輸出1 2 [3,4,5,6]
        console.log(a,b,rest);
    }
3.2.1.1、默認(rèn)值undefined
    // 沒有配對(duì)成功,默認(rèn)值為3;如果=3去掉,c是undefined
    {
        let a, b, c, rest;
        [a, b, c=3] = [1, 2];
        // 輸出1 2 3
        console.log(a, b, c);
    }
3.2.1.2、使用場(chǎng)景
    // 變量交換
    {
        let a = 1;
        let b = 2;
        [a, b] = [b, a];
        // 輸出2 1
        console.log(a, b)
    }
    
    // 取值方便
    {
        function f() {
            return [1,2]
        }
        let a, b;
        [a,b]=f();
        // 輸出1 2
        console.log(a, b)
    }
        
    // 選擇性接收變量
    {
        function f() {
            return [1,2,3,4,5]
        }
        let a,b,c;
        // 兩個(gè)逗號(hào),對(duì)應(yīng)一個(gè)值
        [a,,,b]=f();
        // 輸出1 4
        console.log(a, b)
    }
    
    {
        function f() {
            return [1,2,3,4,5]
        }
        let a,b,c;
        [a,...b]=f();
        // 輸出1 [2,3,4,5]
        console.log(a, b)
    }

3.2.2、對(duì)象解構(gòu)賦值

    // 左側(cè)與右側(cè)都是一個(gè)對(duì)象
    {
        let a,b;
        ({a, b} = {a:1,b:2});
        // 輸出1 2
        console.log(a,b)
    }

    {
        let o={p:42,q:true};
        let {p,q}=o;
        // 輸出:42 true
        console.log(p,q);
    }
3.2.2.1、默認(rèn)值
    {
        let {a = 10, b = 5} = {a: 3};
        // 輸出:3 5
        console.log(a, b);
    }
3.2.2.2、使用場(chǎng)景
    // 獲取json
    {
        let metaData = {
            title: 'abc',
            test:[{
                title:'test',
                desc:'description'
            }]
        }
    
        let {title:esTitle,test:[{title:cnTitle}]} = metaData;
        // 輸出:abc test
        console.log(esTitle, cnTitle)
    }

3.3、正則(案例:lesson3-regexp.js)略

新特性:構(gòu)造函數(shù)的變化、正則方法的擴(kuò)展、u修飾符、y修飾符、s修飾符
    {
        // es5
        let regex = new RegExp('xyz','i');
        let regex2 = new RegExp(/xyz/i);
    
        // 輸出:true true
        console.log(regex.test('xyz123'), regex2.test('xyz123'));
    
        // es6
        // 允許第二個(gè)參數(shù)i覆蓋修飾符ig
        let regex3 = new RegExp(/xyz/ig,'i');
        console.log(regex3.flags)
    }
    
    // y修飾符
    {
        let s = 'bbb_bb_b';
        // g跟y都是全局匹配;但是全局匹配不同點(diǎn)是,g是從上一次匹配繼續(xù)開始查找(只要能找到,就算匹配成功)
        // y是從下一個(gè)匹配,如果第一個(gè)匹配不對(duì),就算匹配失敗
        // 第一步g跟y都可以匹配到bbb
        // 第二步只有g(shù)可以匹配到bb
        let a1 = /b+/g;
        let a2 = /b+/y;
    
        console.log('one',a1.exec(s),a2.exec(s));
        console.log('two',a1.exec(s),a2.exec(s));
    
        // 判斷一個(gè)正則是否使用了y修飾符
        console.log(a1.sticky);
        console.log(a2.sticky);
    }
    
    // u修飾符(1、當(dāng)處理字符串中的正則的長(zhǎng)度大于2的時(shí)候 2、.是修飾小于2個(gè)字節(jié))
    {
        // true: \uD83D\uDC2A當(dāng)成了2個(gè)字母(字符)
        console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A'));
        // false: \uD83D\uDC2A當(dāng)成了1個(gè)字母(字符)
        console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A'));
    
        // 如果{}放的是unicode編碼,要加個(gè)u,才能被識(shí)別
        // false
        console.log(/\u{61}/.test('a'));
        // true
        console.log(/\u{61}/u.test('a'));
    
        // ??
        console.log(`\u{20BB7}`);
    
        let s = '??';
        // false
        console.log('u',/^.$/.test(s))
        // true
        console.log('u',/^.$/u.test(s))
    
        // false
        console.log('test',/??{2}/.test('????'));
        // true
        console.log('test-2',/??{2}/u.test('????'));
    }

3.4、字符串(案例:lesson4-string.js)

新增特性:Unicode表示法、遍歷接口、模板字符串、新增方法(10種)
npm install babel-polyfill --save-dev
label-polyfill.png
    {
        let str = 'string';
        // 查找是否包含了r
        console.log('查找是否包含了r:', str.includes('r'));        // true
        // 判斷是否以str為起始
        console.log('判斷是否以str為起始:',str.startsWith('str'));  // true
        // 判斷是否以ng為結(jié)尾
        console.log('判斷是否以ng為結(jié)尾:',str.endsWith('ng'));      // true
    }
    
    {
        let str = 'abc';
        // 字符串復(fù)制
        console.log('字符串復(fù)制:' + 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
    }
    
    {
        // 通常運(yùn)用在日期
    
        // 向前補(bǔ):長(zhǎng)度是4位,不夠補(bǔ)0
        console.log('1'.padStart(4,'0'));       // 0001
    
        // 向后補(bǔ)
        console.log('1'.padEnd(2,'0'));         // 10
    }

3.5 數(shù)值擴(kuò)展(案例:lesson5-number-math.js)

新增特性:新增方法、方法調(diào)用
    {
        // Number.isFinite()用來檢查一個(gè)數(shù)值是否為有限的
        // 有進(jìn) true
        console.log('15',Number.isFinite(15));
        // 無進(jìn) false
        console.log('NaN',Number.isFinite(NaN));
        // 分母為0 false
        console.log('1/0',Number.isFinite('true'/0));
        // true
        console.log('NaN',Number.isNaN(NaN));
        // false
        console.log('0',Number.isNaN(0));
    }
    
    {
        // 判斷一個(gè)數(shù)是不是整數(shù)
        // true
        console.log('判斷25是不是整數(shù):' + Number.isInteger(25));
        // true
        console.log('判斷25.0數(shù)是不是整數(shù):' + Number.isInteger(25.0));
        // false
        console.log('判斷25.1數(shù)是不是整數(shù):' + Number.isInteger(25.1));
        // false
        console.log('判斷"25.1"數(shù)是不是整數(shù):' + Number.isInteger('25.1'));
        // false
        console.log('判斷"25"數(shù)是不是整數(shù):' + Number.isInteger('25'));
    }
    
    
    {
        // 常量
        // 表示數(shù)的最大上線 9007199254740991
        console.log(Number.MAX_SAFE_INTEGER);
        // 表示數(shù)的最小下線 -9007199254740991
        console.log(Number.MIN_SAFE_INTEGER);
    
        // 10是一個(gè)安全的數(shù) true
        console.log('10', Number.isSafeInteger(10));
        // false
        console.log('a', Number.isSafeInteger('a'));
    }
    
    {
        // Math.trunc取整數(shù)
        // 4
        console.log(4.1,Math.trunc(4.1));
        // 4
        console.log(4.9,Math.trunc(4.9));
    }
    
    {
        // 判斷數(shù)字是正數(shù)還是負(fù)數(shù)
    
        // 負(fù)數(shù)為-1
        console.log('-5',Math.sign(-5));
        // 0為0
        console.log('0',Math.sign(0));
        // 正數(shù)為1
        console.log('5',Math.sign(5));
        // NaN
        console.log('foo',Math.sign('foo'));
    }
    
    {
        // -1的立方根
        console.log('-1的立方根:',Math.cbrt(-1))
        console.log('8的立方根:',Math.cbrt(8))
    }

3.6 數(shù)組擴(kuò)展(案例:lesson6-array.js)

新增特性:Array.from、Array.of、copyWithin、find\findIndex、fill、entries\keys\values、inludes
    {
        // 是一個(gè)數(shù)組
        let arr = Array.of(3,4,7,9,11);
        console.log('arr是一個(gè)數(shù)組' + arr);      // 3,4,7,9,11
    
        // 空數(shù)組
        let empty = Array.of();
        console.log('空數(shù)組:',empty);            // 空數(shù)組: []
    }
    
    {
        let p = document.querySelectorAll('p');
        let pArr = Array.from(p);
        pArr.forEach(function (item) {
            // textContent原生js獲取DOM節(jié)點(diǎn)內(nèi)容
            // es6
            // hjy
            // oli
            console.log(item.textContent);
        });
    
        // 把數(shù)組的里參數(shù)都乘以2
        console.log(Array.from([1,3,5],function (item) {
            return item*2;  // 2,6,10
        }));
    }
    
    {
        // 數(shù)組里的參數(shù)都被替換成7
        console.log('fill-7',[1,'a',undefined].fill(7));    // [7, 7, 7]
        // 從起始位置1,不到3的位置,替換成7
        console.log('fill,post',['a','b','c'].fill(7,1,3)); // ["a", 7, 7]
    }
    
    {
        for(let index of ['1','c','ks'].keys()){
            // 0 1 2
            console.log('keys', index);
        }
    
        for(let value of ['1','c','ks'].values()){
            // 1 c ks
            console.log('values', value);
        }
    
        for(let [index,value] of ['1','c','ks'].entries()){
            // index=0, value=1
            // index=1, value=c
            // index=2, value=ks
            console.log('index=' + index + ', value=' + value);
        }
    }
    
    {
        // Array.prototype.copyWithin(target, start = 0, end = this.length)
        // target(必需):從該位置開始替換數(shù)據(jù)。如果為負(fù)值,表示倒數(shù)。
        // start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0。如果為負(fù)值,表示倒數(shù)。
        // end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長(zhǎng)度。如果為負(fù)值,表示倒數(shù)。
    
        // 從0的位置開始替換,從3開始讀取,從4截止
        // 把4放到1的位置上:[4, 2, 3, 4, 5]
        console.log([1,2,3,4,5].copyWithin(0,3,4));
    }
    
    {
        console.log([1,2,3,4,5,6].find(function (item) {
            // 查找第一個(gè)符合大于3的值(找到了就停止)
            // 返回4
            return item > 3;
        }));
    
        console.log([1,2,3,4,5,6].findIndex(function (item) {
            // 查找第一個(gè)符合大于3的下標(biāo)(找到了就停止)
            // 返回3
            return item > 3;
        }));
    }
    
    {
        // 數(shù)組中是不是包含了1
        // true
        console.log('number',[1,2,NaN].includes(1));
        // true
        console.log('number',[1,2,NaN].includes(NaN));
    }

3.7 函數(shù)擴(kuò)展(案例:lesson7-function.js)

新增特性:參數(shù)默認(rèn)值、rest參數(shù)、擴(kuò)展運(yùn)算符、箭頭函數(shù)、this綁定、尾調(diào)用
    {
        function test(x,y = 'world') {
            // 如果y沒有值,就采用默認(rèn)值為world;如果有值,用采用傳遞過來的參數(shù)
            console.log('默認(rèn)值',x,y)
        }
        test('hello');
        test('hello','hjy');
    
        // 錯(cuò)誤寫法:
        // function test(x,y = 'world',c)
    
        // 正確寫法:
        // function test(x,y = 'world',c='bb')
    }
    
    {
        let x = 'test';
        // 都是取kill
        function test2(x,y=x) {
            console.log("作用域:",x,y);
        }
        // 作用域: kill kill
        test2('kill');
    
    
        function test3(c,y=x) {
            // 作用域: kill test
            console.log("作用域:",c,y);
        }
        test3('kill');
    }
    
    {
        // ...arg不確定傳入幾個(gè)參數(shù),轉(zhuǎn)成一個(gè)數(shù)組
        function test4(...arg) {
            for(let v of arg){
                // rest 1
                // rest 2
                // rest 3
                // rest 4
                // rest a
                console.log('rest',v);
            }
        }
        test4(1,2,3,4,'a');
    }
    
    {
        // 把數(shù)組轉(zhuǎn)成一個(gè)離散的值
        console.log(...[1,2,4]);    // 1 2 4
        console.log('a',...[1,2,4]);// a 1 2 4
    }
    
    {
        // 函數(shù)
        // arrow函數(shù)名 v參數(shù) v*2返回值
        let arrow = v => v*2;
        let arrow2 = () => 5;
    
        console.log('a',arrow(3));  // a 6
        console.log('a',arrow2());  // a 5
    }
    
    {
        // 尾調(diào)用(提升性能:函數(shù)地址嵌套)
        function tail(x) {
            console.log('tail',x);
        }
        function fx(x) {
            return tail(x)
        }
        fx(123)
    }

3.8 對(duì)象擴(kuò)展(案例:lesson8-Obj.js)

新增特性:簡(jiǎn)潔表示法、屬性表達(dá)式、擴(kuò)展運(yùn)算符、Object新增方法
    {
        // 簡(jiǎn)潔表達(dá)
        let o = 1;
        let k = 2;
        let es5 = {
            o:o,
            k:k
        };
    
        let es6 = {
            o,
            k
        };
        console.log(es5,es6);           // {o: 1, k: 2}  {o: 1, k: 2}
    
        // 對(duì)象里有方法
        let es5_method = {
            hello:function () {
                console.log('hello');
            }
        };
        let es6_method = {
            hello(){
                console.log('hello');
            }
        };
        console.log(es5_method.hello(),es6_method.hello());// hello hello
    }
    
    {
        // 屬性表達(dá)式
        let a = 'b';
        let es5_obj = {
            a:'c'
        };
        // [a]是一個(gè)變量
        let es6_obj = {
            [a]:'c'
        };
        // {a: "c"}   {b: "c"}
        console.log(es5_obj,es6_obj)
    }
    
    {
        // 新增API
        // Object.is與三個(gè)等號(hào)相同  輸出:true true
        console.log('判斷2個(gè)字符串是否相等', Object.is('abc','abc'), 'abc' === 'abc');
    
        // 數(shù)組是引用類型,但是數(shù)組引用的是不同地址  輸出:false false
        console.log('數(shù)組',Object.is([],[]), [] === []);
    
        // 當(dāng)個(gè)對(duì)象合并成一個(gè)對(duì)象{a: "a", b: "b"}
        console.log('拷貝', Object.assign({a:'a'}, {b:'b'}));
    
        // 對(duì)數(shù)組進(jìn)行遍歷
        let test = {k:123,o:456};
        for(let [key,value] of Object.entries(test)){
            console.log(key,value);
        }
    }

3.9 symbol(案例:lesson9-symbol.js)

ES6新增加的類型
就是這種數(shù)據(jù)類型,提供一個(gè)獨(dú)一無二(保證唯一)的值
    {
        // 聲明
        let a1 = Symbol();
        let a2 = Symbol();
        // false
        console.log(a1 === a2);
    
        // 'a3'是一個(gè)key值
        let a3 = Symbol.for('a3');
        let a4 = Symbol.for('a3');
        // true
        console.log(a3 === a4);
    }
    
    {
        // 使用場(chǎng)景:兩個(gè)相同的名字,不想去改變
        let a1 = Symbol.for('abc');
        let obj = {
            [a1]:'123',
            'abc':'345',
            'c':456
        };
        console.log(obj);       // {abc: "345", c: 456, Symbol(abc): "123"}
    
        // symbol的值取不到
        for(let [key,value] of Object.entries(obj)){
            // let of abc 345
            // let of c 456
            console.log('let of', key, value);
        }
    
        // 取到symbol的值
        Object.getOwnPropertySymbols(obj).forEach(function (item) {
            // 123
            console.log(obj[item])
        });
    
        // 兩種參數(shù)的值都可以獲取到
        Reflect.ownKeys(obj).forEach(function (item) {
            // ownKeys abc 345
            // ownKeys c 456
            // ownKeys Symbol(abc) 123
            console.log('ownKeys', item, obj[item]);
        })
    }

3.10 set-map數(shù)據(jù)結(jié)構(gòu)(案例:lesson10-set-map.js)

    {
        let list = new Set();
        list.add(5);
        list.add(7);
        // 判斷長(zhǎng)度 輸出:2
        console.log('size',list.size);
    }
    
    {
        let arr = [1,2,3,4,5];
        let list = new Set(arr);
        // 5
        console.log('size', list.size);
    }
    
    {
        // 運(yùn)用場(chǎng)景:去重
        let list = new Set();
        list.add(1);
        list.add(2);
        // 重復(fù)元素,沒有添加成功
        list.add(1);
        // {1, 2}
        console.log('list',list);
    
    
        let arr = [1,2,3,1,2];
        let list2 = new Set(arr);
        // 輸出{1,2,3}
        console.log('unique',list2);
    }
    
    {
        let arr = ['add','delete','clear','has'];
        let list = new Set(arr);
    
        // 判斷l(xiāng)ist里面有沒有add這個(gè)值 輸出:true
        console.log('has', list.has('add'));
        // 刪除list
        console.log('delete', list.delete('add'), list);
        // 清空list
        list.clear();
        console.log('list',list);
    }
    
    {
        let arr = ['add','delete','clear','has'];
        let list = new Set(arr);
    
    
        for(let key of list.keys()){
            // keys add
            // keys delete
            // keys clear
            // keys has
            console.log('keys',key);
        }
        for(let value of list.values()){
            // values add
            // values delete
            // values clear
            // values has
            console.log('values',value);
        }
        for(let value of list){
            // values add
            // values delete
            // values clear
            // values has
            console.log('values',value);
        }
        for(let [key,value] of list.entries()){
            // entries add add
            // entries delete delete
            // entries clear clear
            // entries has has
            console.log('entries',key,value)
        }
    
        list.forEach(function (item) {
            // add
            // delete
            // clear
            // has
            console.log(item);
        })
    }
    
    
    {
        // 和set的數(shù)據(jù)類型不一樣,WeakSet只是能對(duì)象,不能是數(shù)值,例如boolean
        // WeakSet對(duì)象這塊,弱引用(不會(huì)檢測(cè)對(duì)象在其他地方引用到,意味著不會(huì)跟垃圾回收機(jī)制掛鉤到,簡(jiǎn)單說:WeakSet是一個(gè)地址的引用)
        // WeakSet沒有clean、沒有set、不能遍歷
        let weakList = new WeakSet();
    
        let arg = {};
        weakList.add(arg);
        // 報(bào)錯(cuò)
        // weakList.add(2);
        console.log('weakList',weakList);
    }
    
    
    {
        let map = new Map();
        let arr = ['123'];
    
        map.set(arr,456);
        console.log('map', map, map.get(arr));      // key是123 value是456
    }
    
    {
        let map = new Map([['a',123],['b',456]]);
        console.log('map args', map);                   // {"a" => 123, "b" => 456}
        console.log('size', map.size);                  // 2
        console.log('delete', map.delete('a'), map);    // {"b" => 456}
        console.log('clear', map.clear(), map);         // {}
    }
    
    {
        // 與set和weakSet是一樣的
        let weakmap = new WeakMap();
    }

3.11 map-set與數(shù)組和對(duì)象的比較(案例:lesson11-map-set-array-obj.js)

涉及的數(shù)據(jù)結(jié)構(gòu)能使用map,不使用數(shù)組
數(shù)據(jù)的唯一性使用set
    {
        // map 和 array 數(shù)據(jù)結(jié)構(gòu)橫向?qū)Ρ龋涸鰟h改查
        let map = new Map();
        let array = [];
        // 增
        map.set('t',1);
        array.push({t:1});
        console.info('map-array-add',map,array);
    
        // 查
        let map_exist = map.has('t');// true
        let array_exist = array.find(item=>item.t);// 遍歷數(shù)組,查看是否存在;如果存在,就返回值
        console.info('map-array-find', map_exist, array_exist);
    
        // 改(map比較簡(jiǎn)單,array復(fù)雜)
        map.set('t',2);
        array.forEach(item => item.t ? item.t = 2 : '');
        console.info('map-array-modify',map, array);
    
        // 刪(map比較簡(jiǎn)單,array復(fù)雜)
        map.delete('t');
        let index = array.findIndex(item => item.t);
        array.splice(index,1);
        console.info('map-array-remove',map, array);
    }
    
    
    {
        // set 和 array 的對(duì)比
        let set = new Set();
        let array = [];
    
        // 增
        set.add({t:1});
        array.push({t:1});
        console.info('set-array-add', set, array);
    
        // 查
        let set_exist = set.has({t:1});// false
        let array_exist = array.find(item=>item.t);// 遍歷數(shù)組,查看是否存在;如果存在,就返回值
        console.info('set-array-find', set_exist, array_exist);
    
        // 改
        set.forEach(item => item.t ? item.t=2 :'');
        array.forEach(item => item.t ? item.t=2 :'');
        console.info('set-array-modify', set, array);
    
        // 刪(set和array刪除都相對(duì)麻煩)
        set.forEach(item => item.t ? set.delete(item) : '');
        let index = array.findIndex(item => item.t);
        array.splice(index, 1);
        console.info('set-array-remove', set, array);
    }
    
    {
        // set map 和 object 對(duì)比
        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-set-obj', obj, map, set);
    
        // 查(obj不如map和set語義化)
        console.info({
            map_find:map.has('t'),
            set_find:set.has(item),
            obj_find:'t' in obj
        });
    
        // 改
        map.set('t',2);
        item.t = 2;
        obj['t'] = 2;
        console.log('map-set-obj-modify', obj, map, set);
    
        // 刪(set和array刪除都相對(duì)麻煩)
        map.delete('t');
        set.delete(item);
        delete obj['t'];
        console.log('map-set-obj-remove', obj, map, set);
    }

3.12 Proxy 和 Reflect(案例:lesson12-proxy-reflect.js)

Proxy代理,代理商:用戶 和 商家(連接了用戶和最真實(shí)對(duì)象的一個(gè)層)
Reflect反射
    {
        // 供應(yīng)商 原始對(duì)象,存儲(chǔ)真實(shí)數(shù)據(jù)
        let obj = {
            time:'2017-03-11',
            name:'net',
            _r:123
        };
    
        // 代理商
        let monitor = new Proxy(obj, {
            // 攔截(代理)對(duì)象屬性的讀取
            get(target, key){
                // target相當(dāng)于obj
                // console.log(target);
    
                // 把2017替換成2018
                return target[key].replace('2017','2018');
            },
            // 攔截對(duì)象設(shè)置屬性
            set(target, key, value){
                if(key === 'name'){
                    return target[key] = value
                }else {
                    return target[key];
                }
    
            },
            // 攔截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.getOwnPropertyNames
            // 保護(hù)time的key不被用戶看到
            ownKeys(target){
                return Object.keys(target).filter(item=>item!='time')
            }
        });
    
        console.log('get', monitor.time);       // 2018-03-11
    
        monitor.time = '2019';
        monitor.name = 'hjy';
        console.log('set',monitor.time);        // 2018-03-11
        console.log('set',monitor.name);        // hjy
    
        // time被攔截了  true false
        console.log('has','name' in monitor, 'time' in monitor);
    
        // 對(duì)象依舊存在
        // delete monitor.time;
        // console.log('delete', monitor);
    
        // 成功的刪掉_r
        // delete monitor._r;
        // console.log('delete', monitor);
    
        console.log('ownKeys',Object.keys(monitor));
    }
    
    {
        let obj = {
            time:'2017-03-11',
            name:'net',
            _r:123
        };
    
        // 讀取time的值  
        console.log('Reflect get', Reflect.get(obj,'time'));    // 2017-03-11
        // 把name改成hjy
        Reflect.set(obj, 'name', 'hjy');                        
        console.log(obj);                                       // {time: "2017-03-11", name: "hjy", _r: 123}
        // 判斷obj里是否有name
        console.log('has',Reflect.has(obj,'name'));             // true
    }
    
    {
        function validator(target, validator) {
            // 對(duì)target進(jìn)行代理
            return new Proxy(target,{
                // 保存配置選項(xiàng)
                _validator:validator,
                // 對(duì)set進(jìn)行修改
                set(traget,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('hjy',30);
        console.log(person);
    
        // 不能設(shè)置數(shù)字
        // person.name = 48;
        person.name = 'oli';
        console.log(person);
    
    }

3.13 類 和 對(duì)象(案例:lesson13-class.js)

類的概念:基本語法、類的繼承、靜態(tài)方法、靜態(tài)屬性、getter、setter
    {
        // 基本定義和生成實(shí)例
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
        }
        let v_parent = new Parent('v');
        let v_parent2 = new Parent();
        // {name: "v"}
        console.log('構(gòu)造函數(shù)和實(shí)例',v_parent);
        // {name: "hjy"}
        console.log('構(gòu)造函數(shù)和實(shí)例',v_parent2);
    }
    
    {
        // 繼承
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
        }
    
        class Child extends Parent{
    
        }
        // {name: "hjy"}
        console.log('繼承', new Child());
    }
    
    {
        // 繼承傳遞參數(shù)
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
        }
    
        class Child extends Parent{
            constructor(name='child'){
                // 修改父類的參數(shù)(要把super放在第一行)
                super(name);
    
                // 子類增加自己的屬性
                this.type='childType';
            }
        }
        // {name: "lio", type: "childType"}
        console.log('子類向父類傳遞參數(shù)', new Child('lio'));
    }
    
    {
        // getter setter
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
    
            get longName(){
                return '姓名:' + this.name
            }
    
            set longName(value){
                this.name = value;
            }
        }
    
        let v = new Parent();
        // hjy
        console.log('getter',v.longName);
        v.longName='lio';
        // lio
        console.log('setter',v.longName);
    }
    
    {
        // 靜態(tài)方法(通過類調(diào)用,而不是通過類的實(shí)例去調(diào)用)
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
    
            // 靜態(tài)方法
            static tell(){
                console.log('tell');
            }
        }
        // tell
        Parent.tell();
    }
    
    {
        // 靜態(tài)屬性
        class Parent{
            // 構(gòu)造函數(shù)
            constructor(name='hjy'){
                this.name = name;
            }
    
            // 靜態(tài)方法(不能定義靜態(tài)屬性)
            static tell(){
                console.log('tell');
            }
        }
        // 靜態(tài)屬性
        Parent.type = 'test';
        // tell
        console.log('靜態(tài)屬性',Parent.type);
    }

3.14 Promise(案例:lesson14-promise.js)

異步編程的解決方法
A執(zhí)行完再執(zhí)行B,兩種實(shí)現(xiàn)方式:回調(diào)、事件觸發(fā)
    {
        // es5回調(diào)解決異步操作
        let ajax = function (callback) {
            console.log('執(zhí)行');
            setTimeout(function () {
                // 判斷回調(diào)是不是存在,如果存在,執(zhí)行下一步
                callback && callback.call()
            },1000)
        };
        ajax(function () {
            console.log('timeout1');
        });
    }
    
    {
        // es6
        let ajax = function () {
            console.log('執(zhí)行2');
            // 返回一個(gè)Promise實(shí)例(執(zhí)行下一步功能)
            // resolve執(zhí)行下一步操作
            // reject中斷下一步操作
            return new Promise(function (resolve,reject) {
                setTimeout(function () {
                    resolve();
                },1000);
            })
        };
    
        ajax().then(function () {
            console.log('promise','timeout2');
        })
    }
    
    {
        // A執(zhí)行完再執(zhí)行B,B執(zhí)行完了執(zhí)行C ...
        let ajax = function () {
            console.log('執(zhí)行3');
            // 返回一個(gè)Promise實(shí)例(執(zhí)行下一步功能)
            // resolve執(zhí)行下一步操作
            // reject中斷下一步操作
            return new Promise(function (resolve,reject) {
                setTimeout(function () {
                    resolve();
                },1000);
            })
        };
    
        ajax().then(function () {
            return new Promise(function (resolve,reject) {
                // 又可以下一步
                resolve();
            },2000)
        }).then(function () {
            console.log('timeout3');
        })
    }
    
    {
        // catch捕獲錯(cuò)誤
        let ajax = function (num) {
            console.log('執(zhí)行4');
            return new Promise(function (resolve,reject) {
                // 如果大于5,執(zhí)行下一步
                if(num > 5){
                    resolve();
                }else{
                    // 拋出錯(cuò)誤
                    throw new Error('出錯(cuò)了');
                }
            })
        };
    
        ajax(6).then(function () {
            console.log('log',6);
        }).catch(function (err) {
            console.log('catch',err);
        });
    
        ajax(3).then(function () {
            console.log('log',3);
        }).catch(function (err) {
            console.log('catch',err);
        })
    }
    
    {
        // 所有圖片加載完再添加到頁面
        function loadImg(src) {
            return new Promise((resolve,reject) => {
                let img = document.createElement('img');
                img.src = src;
                // 圖片加載完
                img.onload=function () {
                    resolve(img);
                };
                // 圖片加載失敗
                img.onerror = function (err) {
                    reject(err);
                };
            })
        }
    
        function showImgs(imgs) {
            imgs.forEach(function (img) {
                document.body.appendChild(img);
            })
        }
    
        // all:把多個(gè)Promise實(shí)例當(dāng)成一個(gè)Promise實(shí)例
        Promise.all([
            // 三張圖片都加載完,才會(huì)觸發(fā)all,才執(zhí)行then
            loadImg('http://myoli.xin/public/images/banner.jpg'),
            loadImg('http://myoli.xin/public/images/banner.jpg'),
            loadImg('http://myoli.xin/public/images/banner.jpg')
        ]).then(showImgs)
    }
    
    {
        // 有一個(gè)圖片加載完成添加到頁面
        function loadImg(src) {
            return new Promise((resolve,reject) => {
                let img = document.createElement('img');
                img.src = src;
                // 圖片加載完
                img.onload=function () {
                    resolve(img);
                };
                // 圖片加載失敗
                img.onerror = function (err) {
                    reject(err);
                };
            })
        }
    
        function showImgs(img) {
            let p = document.createElement('p');
            p.appendChild(img);
            document.body.appendChild(p)
        }
    
        // 三張圖片,只要有一個(gè)圖片加載出來,那個(gè)就先顯示在頁面上
        Promise.race([
            loadImg('http://myoli.xin/public/images/banner.jpg'),
            loadImg('http://myoli.xin/public/images/banner.jpg'),
            loadImg('http://myoli.xin/public/images/banner.jpg')
        ]).then(showImgs)
    }

3.15 Iterator(案例:lesson15-iterator.js)

操作數(shù)組、object、map、set
    {
        let arr = ['hello','world'];
        let map = arr[Symbol.iterator]();
        // {value: "hello", done: false}
        console.log(map.next());
        // {value: "world", done: false}
        console.log(map.next());
        // {value: undefined, done: true}  true代表沒有下一步
        console.log(map.next());
    }
    
    {
        // 自定義iterator接口
        // obj數(shù)據(jù)是我們自己填充
        let obj = {
            start:[1,3,2],
            end:[7,9,8],
            // Symbol.iterator變量名
            [Symbol.iterator](){
                let self = this;
                // 記錄當(dāng)前遍歷索引
                let index = 0;
                // start和end合并成一個(gè)數(shù)組
                let arr = self.start.concat(self.end);
                // 記錄數(shù)組的長(zhǎng)度
                let len = arr.length;
                return {
                    next(){
                        if(index < len){
                            return {
                                value:arr[index++],
                                done:false
                            }
                        } else {
                            return {
                                value:arr[index++],
                                done:true
                            }
                        }
                    }
                }
            }
        }
    
        for(let key of obj){
            console.log(key);
        }
    }
    
    
    {
        // 對(duì)數(shù)組進(jìn)行遍歷
        let arr = ['hello','world'];
        for(let value of arr){
            // hello
            // world
            console.log('value',value);
        }
    }

3.16 Generator(案例:lesson16-decorators.js)

異步編程的一種解決方案
    {
        // genertaor基本定義
        // 與普通的函數(shù)不同:* 、 yield
        let tell = function* () {
            yield 'a';
            yield 'b';
            return 'c';
        };
    
        // 調(diào)用tell,執(zhí)行到第一個(gè)yield停止下來
        let k = tell();
    
        // 執(zhí)行第一個(gè)yield
        // {value: "a", done: false}
        console.log(k.next());
    
        // 執(zhí)行第二個(gè)yield
        // {value: "b", done: false}
        console.log(k.next());
    
        // 執(zhí)行retrun
        // {value: "c", done: true}
        console.log(k.next());
    
        // {value: undefined, done: true}
        console.log(k.next());
    }
    
    {
        // of遍歷
        let obj = {
    
        };
        obj[Symbol.iterator] = function* () {
            yield 1;
            yield 2;
            yield 3;
        };
    
        for(let value of obj){
            // 1
            // 2
            // 3
            console.log('value',value);
        }
    }
    
    {
        let state = function* () {
            while(1){
                yield 'A';
                yield 'b';
                yield 'c';
            }
        }
        let status = state();
        // {value: "A", done: false}
        // {value: "b", done: false}
        // {value: "c", done: false}
        // {value: "A", done: false}
        // {value: "b", done: false}
        console.log(status.next());
        console.log(status.next());
        console.log(status.next());
        console.log(status.next());
        console.log(status.next());
    }
    
    {
        // 抽獎(jiǎng)
        let draw = function (count) {
            // 具體抽獎(jiǎng)邏輯
            console.info(`剩余${count}次`);
        };
    
        let residue = function* (count) {
            while (count > 0){
                count--;
                yield draw(count);
            }
        };
    
        // 可以抽獎(jiǎng)5次,如果是最后一次,點(diǎn)擊無效
        let star = residue(5);
        let btn = document.createElement('button');
        btn.id = 'start';
        btn.textContent = '抽獎(jiǎng)';
        document.body.appendChild(btn);
        document.getElementById('start').addEventListener('click',function () {
            star.next();
        },false)
    }
    
    {
        // 長(zhǎng)輪詢(接口請(qǐng)求失敗,一直請(qǐng)求)
        let ajax = function* () {
            yield new Promise(function (resolve,reject) {
                // 接口
                setTimeout(function () {
                    resolve({code:0})
                },200);
            })
    
        };
    
        let pull = function () {
            let genertaor = ajax();
            let step = genertaor.next();
            step.value.then(function (d) {
                if(d.code != 0){
                    setTimeout(function () {
                        console.log('wait');
                        pull();
                    },1000);
                }else{
                    console.log(d);
                }
            })
        };
    
        pull();
    }

3.17 Decorator(案例:lesson17-decorators.js)

修飾器:是一個(gè)函數(shù),修改類的行為(擴(kuò)展類的動(dòng)能,只在類里修改有用)
    {
        // 是一個(gè)函數(shù)
        let readonly = function (target, name, descriptor) {
            descriptor.writable = false;
            return descriptor
        };
    
        // 修改類的行為
        class Test{
            // 加了修飾器,就是不能重新修改參數(shù);只有只讀的狀態(tài)
            // @readonly與上面的readonly要一致
            @readonly
            time(){
                return '2017-03-11'
            }
        }
    
        let test = new Test();
        // 加了修飾器,就是不能重新修改參數(shù);只有只讀的狀態(tài)
        // 報(bào)錯(cuò)
        // test.time = function () {
        //     console.log('reset name')
        // }
        // 2017-03-11
        console.log(test.time())
    }
    
    
    {
        let typename = function (target,name,descriptor) {
            // 靜態(tài)屬性
            target.myname = 'hello';
        };
    
        // 修飾器(對(duì)類進(jìn)行修飾)
        @typename
        class Test{
    
        }
        console.log('類修飾符',Test.myname);    // hello
        // 第三方庫修飾器的js庫:core-decorators; npm install core-decorators
    }
    
    {
        // 看廣告是show還是click
        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.info('ad is show');
            }
    
            @log('click')
            click(){
                console.info('ad is click');
            }
    
        }
    
        // 實(shí)例化
        let ad = new AD();
        ad.show();
        ad.click();
    }

3.18 模塊化(案例:lesson18-module.js)

    let A = 123;
    let test = function () {
        console.log('test');
    }
    class Hello{
        test(){
            console.log('class');
        }
    }
    export default {
        A,
        test,
        Hello
    }
    
    // 模塊化:導(dǎo)入所有 lesson只是一個(gè)別名
    import * as lesson from './class/lesson18-module';
    console.log(lesson.A);
    console.log(lesson.test);
    
    import Lesson18 from './class/lesson18-module';
    console.log(Lesson18.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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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