美文网首页
【呕心整理】ES6入门基础,包含运行代码

【呕心整理】ES6入门基础,包含运行代码

作者: 无懈可击 | 来源:发表于2021-05-03 23:24 被阅读0次

    ES6入门基础

    推荐书籍 《ECMAScript 6 入门》:http://es6.ruanyifeng.com/
    

    码云仓库代码(欢迎Start)

    码云仓库代码-https://gitee.com/hongjunyong/es6-imooc-lottery

    1、为什么要学习ES6

    detail.png

    1.1、对象拷贝

    copy.png

    1.2、参数传递

    data.png

    1.3、更多特性:解构赋值、箭头函数、set和map、异步操作、类与对象、模块化

    2、项目构建(略)

        // -e要使用ejs模版引擎 .当前目录执行
        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
        
        项目运行 gulp --watch
    

    3、ES6语法

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

    3.1.1、let的生命周期

        // i在for循环外面依旧有效
        for(var i=1;i<3;i++){
            console.log(i);
        }
        console.log(i);
    
        // i只有在for循环里面有效,出了括号生命周期结束
        for(let i=1;i<3;i++){
            console.log(i);
        }
        console.log(i);
    
    let.png

    3.1.2、let变量不能重复定义

        错误:
            let a = 1;
            let a = 2;
    

    3.1.3、const常量不能修改,对象可以修改(指针),且声明的时候必须赋值

        const常量不能修改
            错误:
                const a = 1;
                a = 2;
    
        对象可以修改
            正确:
                const k = {
                    a:1
                }
                k.b = 3;
        
        声明的时候必须赋值
            错误:
                const a;
                a = 1;
            正确:
                const a = 1;
    

    3.1.4、es6开启严格模式('use strict')

    3.1.4.1 不允许使用未声明的变量
        "use strict";
        x = 3.14;                // 报错 (x 未定义)
    
    3.1.4.2 不允许使用未声明的变量(对象也是一个变量)
        "use strict";
        x = { p1: 10,  p2: 20 };      // 报错 (x 未定义)
    
    3.1.4.3 不允许删除变量或对象
        "use strict";
        var x = 3.14;
        delete x;                // 报错
    
    3.1.4.4 不允许删除函数
        "use strict";
        function x(p1, p2) {}; 
        delete x;                // 报错
    
    3.1.4.5 不允许变量重名
        "use strict";
        function x(p1, p1) {};   // 报错
    
    3.1.4.6 不允许使用八进制
        "use strict";
        var x = 010;             // 报错
    
    3.1.4.7 不允许使用转义字符
        "use strict";
        var x = \010;            // 报错
    
    3.1.4.8 不允许对只读属性赋值
        "use strict";
        var obj = {};
        Object.defineProperty(obj, "x", {value:1, writable:false});
        console.log(obj);        // 输出{x: 1}
        obj.x = 3.14;            // 报错
    
    3.1.4.9 不允许对一个使用getter方法读取的属性进行赋值
        "use strict";
        var obj = {get x() {return 0} };
        obj.x = 3.14;            // 报错
    
    3.1.4.10 不允许删除一个不允许删除的属性
        "use strict";
        delete Object.prototype; // 报错
    
    3.1.4.11 变量名不能使用 "eval" 字符串
        "use strict";
        var eval = 3.14;         // 报错
    
    3.1.4.12 变量名不能使用 "arguments" 字符串:
        "use strict";
        var arguments = 3.14;    // 报错
    
    3.1.4.13 全局的'use strict',函数内的变量也声明
        "use strict";
        myFunction();
        
        function myFunction() {
            y = 3.14;   // 报错 (y 未定义)
        }
    
    3.1.4.14 函数内部声明是局部作用域 (只在函数内使用严格模式):
        x = 3.14;       // 不报错 
        myFunction();
        
        function myFunction() {
           "use strict";
            y = 3.14;   // 报错 (y 未定义)
        }
    
    3.1.4.4 为什么使用严格模式:
    消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
    消除代码运行的一些不安全之处,保证代码运行的安全;
    提高编译器效率,增加运行速度;
    为未来新版本的Javascript做好铺垫。
    "严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。
    

    3.2、解构赋值(案例:lesson2-jiegou.js)

    解构赋值的分类:数组解构赋值、对象解构赋值、字符串解构赋值、布尔值解构赋值、函数参数解构赋值、数值解构赋值
    

    3.2.1、数组解构赋值

        // 块作用域:变量的重复声明,用块包起来就不会出现问题
        {}
        
        {
            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、默认值undefined
        // 没有配对成功,默认值为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、使用场景
        // 变量交换
        {
            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;
            // 两个逗号,对应一个值
            [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、对象解构赋值

        // 左侧与右侧都是一个对象
        {
            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、默认值
        {
            let {a = 10, b = 5} = {a: 3};
            // 输出:3 5
            console.log(a, b);
        }
    
    3.2.2.2、使用场景
        // 获取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)略

    新特性:构造函数的变化、正则方法的扩展、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
            // 允许第二个参数i覆盖修饰符ig
            let regex3 = new RegExp(/xyz/ig,'i');
            console.log(regex3.flags)
        }
        
        // y修饰符
        {
            let s = 'bbb_bb_b';
            // g跟y都是全局匹配;但是全局匹配不同点是,g是从上一次匹配继续开始查找(只要能找到,就算匹配成功)
            // y是从下一个匹配,如果第一个匹配不对,就算匹配失败
            // 第一步g跟y都可以匹配到bbb
            // 第二步只有g可以匹配到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));
        
            // 判断一个正则是否使用了y修饰符
            console.log(a1.sticky);
            console.log(a2.sticky);
        }
        
        // u修饰符(1、当处理字符串中的正则的长度大于2的时候 2、.是修饰小于2个字节)
        {
            // true: \uD83D\uDC2A当成了2个字母(字符)
            console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A'));
            // false: \uD83D\uDC2A当成了1个字母(字符)
            console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A'));
        
            // 如果{}放的是unicode编码,要加个u,才能被识别
            // 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为结尾
            console.log('判断是否以ng为结尾:',str.endsWith('ng'));      // true
        }
        
        {
            let str = 'abc';
            // 字符串复制
            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
        }
        
        {
            // 通常运用在日期
        
            // 向前补:长度是4位,不够补0
            console.log('1'.padStart(4,'0'));       // 0001
        
            // 向后补
            console.log('1'.padEnd(2,'0'));         // 10
        }
    

    3.5 数值扩展(案例:lesson5-number-math.js)

    新增特性:新增方法、方法调用
    
        {
            // Number.isFinite()用来检查一个数值是否为有限的
            // 有进 true
            console.log('15',Number.isFinite(15));
            // 无进 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));
        }
        
        {
            // 判断一个数是不是整数
            // true
            console.log('判断25是不是整数:' + Number.isInteger(25));
            // true
            console.log('判断25.0数是不是整数:' + Number.isInteger(25.0));
            // false
            console.log('判断25.1数是不是整数:' + Number.isInteger(25.1));
            // false
            console.log('判断"25.1"数是不是整数:' + Number.isInteger('25.1'));
            // false
            console.log('判断"25"数是不是整数:' + Number.isInteger('25'));
        }
        
        
        {
            // 常量
            // 表示数的最大上线 9007199254740991
            console.log(Number.MAX_SAFE_INTEGER);
            // 表示数的最小下线 -9007199254740991
            console.log(Number.MIN_SAFE_INTEGER);
        
            // 10是一个安全的数 true
            console.log('10', Number.isSafeInteger(10));
            // false
            console.log('a', Number.isSafeInteger('a'));
        }
        
        {
            // Math.trunc取整数
            // 4
            console.log(4.1,Math.trunc(4.1));
            // 4
            console.log(4.9,Math.trunc(4.9));
        }
        
        {
            // 判断数字是正数还是负数
        
            // 负数为-1
            console.log('-5',Math.sign(-5));
            // 0为0
            console.log('0',Math.sign(0));
            // 正数为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 数组扩展(案例:lesson6-array.js)

    新增特性:Array.from、Array.of、copyWithin、find\findIndex、fill、entries\keys\values、inludes
    
        {
            // 是一个数组
            let arr = Array.of(3,4,7,9,11);
            console.log('arr是一个数组' + arr);      // 3,4,7,9,11
        
            // 空数组
            let empty = Array.of();
            console.log('空数组:',empty);            // 空数组: []
        }
        
        {
            let p = document.querySelectorAll('p');
            let pArr = Array.from(p);
            pArr.forEach(function (item) {
                // textContent原生js获取DOM节点内容
                // es6
                // hjy
                // oli
                console.log(item.textContent);
            });
        
            // 把数组的里参数都乘以2
            console.log(Array.from([1,3,5],function (item) {
                return item*2;  // 2,6,10
            }));
        }
        
        {
            // 数组里的参数都被替换成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(必需):从该位置开始替换数据。如果为负值,表示倒数。
            // start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
            // end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
        
            // 从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) {
                // 查找第一个符合大于3的值(找到了就停止)
                // 返回4
                return item > 3;
            }));
        
            console.log([1,2,3,4,5,6].findIndex(function (item) {
                // 查找第一个符合大于3的下标(找到了就停止)
                // 返回3
                return item > 3;
            }));
        }
        
        {
            // 数组中是不是包含了1
            // true
            console.log('number',[1,2,NaN].includes(1));
            // true
            console.log('number',[1,2,NaN].includes(NaN));
        }
    

    3.7 函数扩展(案例:lesson7-function.js)

    新增特性:参数默认值、rest参数、扩展运算符、箭头函数、this绑定、尾调用
    
        {
            function test(x,y = 'world') {
                // 如果y没有值,就采用默认值为world;如果有值,用采用传递过来的参数
                console.log('默认值',x,y)
            }
            test('hello');
            test('hello','hjy');
        
            // 错误写法:
            // 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不确定传入几个参数,转成一个数组
            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');
        }
        
        {
            // 把数组转成一个离散的值
            console.log(...[1,2,4]);    // 1 2 4
            console.log('a',...[1,2,4]);// a 1 2 4
        }
        
        {
            // 函数
            // arrow函数名 v参数 v*2返回值
            let arrow = v => v*2;
            let arrow2 = () => 5;
        
            console.log('a',arrow(3));  // a 6
            console.log('a',arrow2());  // a 5
        }
        
        {
            // 尾调用(提升性能:函数地址嵌套)
            function tail(x) {
                console.log('tail',x);
            }
            function fx(x) {
                return tail(x)
            }
            fx(123)
        }
    

    3.8 对象扩展(案例:lesson8-Obj.js)

    新增特性:简洁表示法、属性表达式、扩展运算符、Object新增方法
    
        {
            // 简洁表达
            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}
        
            // 对象里有方法
            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
        }
        
        {
            // 属性表达式
            let a = 'b';
            let es5_obj = {
                a:'c'
            };
            // [a]是一个变量
            let es6_obj = {
                [a]:'c'
            };
            // {a: "c"}   {b: "c"}
            console.log(es5_obj,es6_obj)
        }
        
        {
            // 新增API
            // Object.is与三个等号相同  输出:true true
            console.log('判断2个字符串是否相等', Object.is('abc','abc'), 'abc' === 'abc');
        
            // 数组是引用类型,但是数组引用的是不同地址  输出:false false
            console.log('数组',Object.is([],[]), [] === []);
        
            // 当个对象合并成一个对象{a: "a", b: "b"}
            console.log('拷贝', Object.assign({a:'a'}, {b:'b'}));
        
            // 对数组进行遍历
            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新增加的类型
    就是这种数据类型,提供一个独一无二(保证唯一)的值
    
        {
            // 声明
            let a1 = Symbol();
            let a2 = Symbol();
            // false
            console.log(a1 === a2);
        
            // 'a3'是一个key值
            let a3 = Symbol.for('a3');
            let a4 = Symbol.for('a3');
            // true
            console.log(a3 === a4);
        }
        
        {
            // 使用场景:两个相同的名字,不想去改变
            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])
            });
        
            // 两种参数的值都可以获取到
            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数据结构(案例:lesson10-set-map.js)

        {
            let list = new Set();
            list.add(5);
            list.add(7);
            // 判断长度 输出:2
            console.log('size',list.size);
        }
        
        {
            let arr = [1,2,3,4,5];
            let list = new Set(arr);
            // 5
            console.log('size', list.size);
        }
        
        {
            // 运用场景:去重
            let list = new Set();
            list.add(1);
            list.add(2);
            // 重复元素,没有添加成功
            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);
        
            // 判断list里面有没有add这个值 输出: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的数据类型不一样,WeakSet只是能对象,不能是数值,例如boolean
            // WeakSet对象这块,弱引用(不会检测对象在其他地方引用到,意味着不会跟垃圾回收机制挂钩到,简单说:WeakSet是一个地址的引用)
            // WeakSet没有clean、没有set、不能遍历
            let weakList = new WeakSet();
        
            let arg = {};
            weakList.add(arg);
            // 报错
            // 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与数组和对象的比较(案例:lesson11-map-set-array-obj.js)

    涉及的数据结构能使用map,不使用数组
    数据的唯一性使用set
    
        {
            // map 和 array 数据结构横向对比:增删改查
            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);// 遍历数组,查看是否存在;如果存在,就返回值
            console.info('map-array-find', map_exist, array_exist);
        
            // 改(map比较简单,array复杂)
            map.set('t',2);
            array.forEach(item => item.t ? item.t = 2 : '');
            console.info('map-array-modify',map, array);
        
            // 删(map比较简单,array复杂)
            map.delete('t');
            let index = array.findIndex(item => item.t);
            array.splice(index,1);
            console.info('map-array-remove',map, array);
        }
        
        
        {
            // set 和 array 的对比
            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);// 遍历数组,查看是否存在;如果存在,就返回值
            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删除都相对麻烦)
            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 对比
            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删除都相对麻烦)
            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代理,代理商:用户 和 商家(连接了用户和最真实对象的一个层)
    Reflect反射
    
        {
            // 供应商 原始对象,存储真实数据
            let obj = {
                time:'2017-03-11',
                name:'net',
                _r:123
            };
        
            // 代理商
            let monitor = new Proxy(obj, {
                // 拦截(代理)对象属性的读取
                get(target, key){
                    // target相当于obj
                    // console.log(target);
        
                    // 把2017替换成2018
                    return target[key].replace('2017','2018');
                },
                // 拦截对象设置属性
                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
                // 保护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);
        
            // 对象依旧存在
            // 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) {
                // 对target进行代理
                return new Proxy(target,{
                    // 保存配置选项
                    _validator:validator,
                    // 对set进行修改
                    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(`不能设置${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);
        
            // 不能设置数字
            // person.name = 48;
            person.name = 'oli';
            console.log(person);
        
        }
    

    3.13 类 和 对象(案例:lesson13-class.js)

    类的概念:基本语法、类的继承、静态方法、静态属性、getter、setter
    
        {
            // 基本定义和生成实例
            class Parent{
                // 构造函数
                constructor(name='hjy'){
                    this.name = name;
                }
            }
            let v_parent = new Parent('v');
            let v_parent2 = new Parent();
            // {name: "v"}
            console.log('构造函数和实例',v_parent);
            // {name: "hjy"}
            console.log('构造函数和实例',v_parent2);
        }
        
        {
            // 继承
            class Parent{
                // 构造函数
                constructor(name='hjy'){
                    this.name = name;
                }
            }
        
            class Child extends Parent{
        
            }
            // {name: "hjy"}
            console.log('继承', new Child());
        }
        
        {
            // 继承传递参数
            class Parent{
                // 构造函数
                constructor(name='hjy'){
                    this.name = name;
                }
            }
        
            class Child extends Parent{
                constructor(name='child'){
                    // 修改父类的参数(要把super放在第一行)
                    super(name);
        
                    // 子类增加自己的属性
                    this.type='childType';
                }
            }
            // {name: "lio", type: "childType"}
            console.log('子类向父类传递参数', new Child('lio'));
        }
        
        {
            // getter setter
            class Parent{
                // 构造函数
                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);
        }
        
        {
            // 静态方法(通过类调用,而不是通过类的实例去调用)
            class Parent{
                // 构造函数
                constructor(name='hjy'){
                    this.name = name;
                }
        
                // 静态方法
                static tell(){
                    console.log('tell');
                }
            }
            // tell
            Parent.tell();
        }
        
        {
            // 静态属性
            class Parent{
                // 构造函数
                constructor(name='hjy'){
                    this.name = name;
                }
        
                // 静态方法(不能定义静态属性)
                static tell(){
                    console.log('tell');
                }
            }
            // 静态属性
            Parent.type = 'test';
            // tell
            console.log('静态属性',Parent.type);
        }
    

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

    异步编程的解决方法
    A执行完再执行B,两种实现方式:回调、事件触发
    
        {
            // es5回调解决异步操作
            let ajax = function (callback) {
                console.log('执行');
                setTimeout(function () {
                    // 判断回调是不是存在,如果存在,执行下一步
                    callback && callback.call()
                },1000)
            };
            ajax(function () {
                console.log('timeout1');
            });
        }
        
        {
            // es6
            let ajax = function () {
                console.log('执行2');
                // 返回一个Promise实例(执行下一步功能)
                // resolve执行下一步操作
                // reject中断下一步操作
                return new Promise(function (resolve,reject) {
                    setTimeout(function () {
                        resolve();
                    },1000);
                })
            };
        
            ajax().then(function () {
                console.log('promise','timeout2');
            })
        }
        
        {
            // A执行完再执行B,B执行完了执行C ...
            let ajax = function () {
                console.log('执行3');
                // 返回一个Promise实例(执行下一步功能)
                // resolve执行下一步操作
                // 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捕获错误
            let ajax = function (num) {
                console.log('执行4');
                return new Promise(function (resolve,reject) {
                    // 如果大于5,执行下一步
                    if(num > 5){
                        resolve();
                    }else{
                        // 抛出错误
                        throw new Error('出错了');
                    }
                })
            };
        
            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:把多个Promise实例当成一个Promise实例
            Promise.all([
                // 三张图片都加载完,才会触发all,才执行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)
        }
        
        {
            // 有一个图片加载完成添加到页面
            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)
            }
        
            // 三张图片,只要有一个图片加载出来,那个就先显示在页面上
            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)

    操作数组、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数据是我们自己填充
            let obj = {
                start:[1,3,2],
                end:[7,9,8],
                // Symbol.iterator变量名
                [Symbol.iterator](){
                    let self = this;
                    // 记录当前遍历索引
                    let index = 0;
                    // start和end合并成一个数组
                    let arr = self.start.concat(self.end);
                    // 记录数组的长度
                    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);
            }
        }
        
        
        {
            // 对数组进行遍历
            let arr = ['hello','world'];
            for(let value of arr){
                // hello
                // world
                console.log('value',value);
            }
        }
    

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

    异步编程的一种解决方案
    
        {
            // genertaor基本定义
            // 与普通的函数不同:* 、 yield
            let tell = function* () {
                yield 'a';
                yield 'b';
                return 'c';
            };
        
            // 调用tell,执行到第一个yield停止下来
            let k = tell();
        
            // 执行第一个yield
            // {value: "a", done: false}
            console.log(k.next());
        
            // 执行第二个yield
            // {value: "b", done: false}
            console.log(k.next());
        
            // 执行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());
        }
        
        {
            // 抽奖
            let draw = function (count) {
                // 具体抽奖逻辑
                console.info(`剩余${count}次`);
            };
        
            let residue = function* (count) {
                while (count > 0){
                    count--;
                    yield draw(count);
                }
            };
        
            // 可以抽奖5次,如果是最后一次,点击无效
            let star = residue(5);
            let btn = document.createElement('button');
            btn.id = 'start';
            btn.textContent = '抽奖';
            document.body.appendChild(btn);
            document.getElementById('start').addEventListener('click',function () {
                star.next();
            },false)
        }
        
        {
            // 长轮询(接口请求失败,一直请求)
            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)

    修饰器:是一个函数,修改类的行为(扩展类的动能,只在类里修改有用)
    
        {
            // 是一个函数
            let readonly = function (target, name, descriptor) {
                descriptor.writable = false;
                return descriptor
            };
        
            // 修改类的行为
            class Test{
                // 加了修饰器,就是不能重新修改参数;只有只读的状态
                // @readonly与上面的readonly要一致
                @readonly
                time(){
                    return '2017-03-11'
                }
            }
        
            let test = new Test();
            // 加了修饰器,就是不能重新修改参数;只有只读的状态
            // 报错
            // test.time = function () {
            //     console.log('reset name')
            // }
            // 2017-03-11
            console.log(test.time())
        }
        
        
        {
            let typename = function (target,name,descriptor) {
                // 静态属性
                target.myname = 'hello';
            };
        
            // 修饰器(对类进行修饰)
            @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');
                }
        
            }
        
            // 实例化
            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
        }
        
        // 模块化:导入所有 lesson只是一个别名
        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);
    

    相关文章

      网友评论

          本文标题:【呕心整理】ES6入门基础,包含运行代码

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