美文网首页
ES6 语法总结

ES6 语法总结

作者: 千反田爱瑠爱好者 | 来源:发表于2018-08-22 01:01 被阅读13次

1. let,const关键词

// ES6强制开启严格模式(ES5:use strict)
function test() {
    for (let i = 1; i < 3; i++) {
        console.log(i);     
    }
    console.log(i);     // 错误:let声明变量作用域为块作用域(不能在花括号外引用);
    
    let a = 1;           // 错误:使用let不能重复声明
    let a = 2;
}

function last() {
    const PI = 3.1415926;   // const声明变量是块作用域,声明时必须赋值
    const k = {             // const声明变量为常量,const声明对象时内部指针可以改变
        a: 1
    };
    k.b = 3;
    console.log(PI, k);
}

test();
last();

2. 结构赋值

// 数组结构赋值
{
    let a, b, rest;
    [a, b] = [1, 2];
    console.log(a, b);          // let a = 1, b = 2;
}
{
    let a, b, rest;
    [a, b, ...rest] = [1, 2, 3, 4, 5, 6];
    console.log(a, b, rest);    // let a = 1, b = 2, rest = [3, 4, 5, 6]
}

// 对象结构赋值
{
    let a, b;
    ({a, b} = {a: 1, b: 2});    // let a = 1, b = 2;
    console.log(a, b);
}
{
    let a, b, c, rest;
    [a, b, c = 3] = [1, 2];     // 如果c没有默认值,则会undefined
    console.log(a, b, c);
}
{
    let a = 1;
    let b = 2;
    [a, b] = [b, a];            // 变量交换
    console.log(a, b);
}
{
    function f() {
        return [1, 2]
    }

    let a, b;
    [a, b] = f();               // 多个返回值(解包)
    console.log(a, b);
}
{
    function f() {
        return [1, 2, 3, 4, 5]
    }

    let a, b, c;
    [a, , , b] = f();           // 只获取特定位置上的返回值
    console.log(a, b);
}
{
    function f() {
        return [1, 2, 3, 4, 5]
    }

    let a, b, c;
    [a, , ...b] = f();          // 跳过不需要的返回值,并把剩余的不定个值赋到数组上
    console.log(a, b);
}
{
    let o = {p: 42, q: true};   
    let {p, q} = o;             // 传递后解包赋值
    console.log(p, q);
}

{
    let {a = 10, b = 5} = {a: 3};       
    console.log(a, b);          // let a = 3, b = 5
}

{
    let metaData = {
        title: 'abc',
        test: [{
            title: 'test',
            desc: 'description'
        }]
    };
    let {title: esTitle, test: [{title: cnTitle}]} = metaData;      // 左右格式一致,则可以获取对应位置上的值
    console.log(esTitle, cnTitle);          // let esTitle = 'abc', enTitle = 'test'
    Object.assign(metaData, {'title': 'def'})        // 对metaData的title赋值为def
}

3. 正则扩展

{
    // // ES5的正则对象构造函数
    let regex = new RegExp('xyz', 'i');         // 第一个参数是字符串,第二个是修饰符
    let regex2 = new RegExp(/xyz/i);            // 第一个参数是正则表达式,不接受第二个参数,否则会报错

    console.log(regex.test('xyz123'), regex2.test('xyz123'));       // true, true

    let regex3 = new RegExp(/abc/ig, 'i');
    console.log(regex3.flags);                  // 原有正则对象的修饰符是ig,它会被第二个参数i覆盖
}

// 字符串对象的4个使用正则表达式的方法: match(),replace(),search(),split()这四个方法全部调用RegExp的实例的方法。
// {
//     let regex = new RegExp('xyz', 'ig');
//     console.log(regex.test('xyz0XYZ1xyz2'), regex.exec('xyz0XYZ1xyz2'));
// }

// y修饰符
{
    let s = 'bbbb_bbb_bb_b';

    let a1 = /b+/g;
    let a2 = /b+/y;

    console.log(a1.exec(s), a2.exec(s));        // ["bbbb"],["bbbb"]
    console.log(a1.exec(s), a2.exec(s));        // ["bbb"],null

    console.log(a1.sticky, a2.sticky);          //表示是否开启了粘连模式
}

// u修饰符(Unicode编码,正则表达式中待匹配的字符串含有大于0xFFFF的字符则必须加u)
{
    console.log('u修饰符', /^\uD83D/.test('\uD83D\uDC2A'));          // true
    console.log('u修饰符', /^\uD83D/u.test('\uD83D\uDC2A'));         // false(u把后面当成一个字符)

    // 大括号表示Unicode字符,只有加上u才能识别
    console.log(/\u{61}/.test('a'));                                 // false
    console.log(/\u{61}/u.test('a'));                                // true
    console.log(/\u{20BB7}/u.test('𠮷'));                            // true

    // 点(.)字符不能识别码点大于0xFFFF的Unicode字符,必须加上u修饰符。
    let s = '𠮷';
    console.log('大于0xFFFF的Unicode字符', /^.$/.test(s)); // false
    console.log('使用u字符', /^.$/u.test(s)); // true

    // 使用u修饰符后,所有量词都会正确识别大于码点大于0xFFFF的Unicode字符。
    console.log('量词', /a{2}/.test('aa'));                          // true
    console.log('量词', /a{2}/u.test('aa'));                         // true
    console.log('量词', /𠮷{2}/.test('𠮷𠮷'));                       // false
    console.log('量词', /𠮷{2}/u.test('𠮷𠮷'));                      // true
}

{
    // 正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符(line terminator character)除外
    // U+000A 换行符(\n)
    // U+000D 回车符(\r)
    // U+2028 行分隔符(line separator)
    // U+2029 段分隔符(paragraph separator)
    // 只是一个提案目前还不支持
    // let reg=/test.go/s;
    // console.log(reg.test('test\ngo'));
    // console.log(reg.test('test\ngo'));
    console.log('s变通方法', /foo.bar/.test('foo\nbar'));
    console.log('s变通方法', /foo[^]bar/.test('foo\nbar'));
}

4. 字符串扩展


// Unicode字符表示
{
    console.log('a', `\u0061`);             // 反引号把Unicode转换成字符串
    console.log('s', `\u20BB7`);            // 大于0xFFFF时不能按一个字符处理,需要使用花括号
    console.log('s', `\u{20BB7}`);
}
{
    let s = '𠮷';
    console.log('length', s.length);        // 2
    console.log('0', s.charAt(0));
    console.log('1', s.charAt(1));
    console.log('at0', s.charCodeAt(0));
    console.log('at1', s.charCodeAt(1));

    let s1 = '𠮷a';
    console.log('length', s1.length);
    console.log('code0', s1.codePointAt(0));                // 134071(10进制)
    console.log('code0', s1.codePointAt(0).toString(16));   // 20BB7(16禁止)
    console.log('code1', s1.codePointAt(1));                // 57271
    console.log('code2', s1.codePointAt(2));
}
{
    console.log(String.fromCharCode("0x20bb7"));            // xxx
    console.log(String.fromCodePoint("0x20bb7"));           // 吉
}
{
    let str = '\u{20bb7}abc';
    for (let i = 0; i < str.length; i++) {
        console.log('es5', str[i]);
    }
    for (let code of str) {                                 // 字符串遍历
        console.log('es6', code);
    }
}

// 字符串扩展
{
    let str = "string";
    console.log('includes', str.includes("c"));
    console.log('start', str.startsWith('str'));
    console.log('end', str.endsWith('ng'));
}
{
    let str = "abc";
    console.log(str.repeat(2));                             // 字符串重复2此
}

// 字符串模板
{
    let name = "list";
    let info = "hello world";
    let m = `i am ${name},${info}`;                         // 反引号定义嵌入模板字符串(scala为s,python为f)
    console.log(m);
}

{
    console.log('1'.padStart(2, '0'));                      // 字符串必须满足长度为2,不足则以0补全
    console.log('1'.padEnd(2, '0'));
}

{
    // 标签模板(防止csrf攻击)
    let user = {
        name: 'list',
        info: 'hello world'
    };
    console.log(`i am ${user.name},${user.info}`);          // i am list,hello world
    console.log(abc`i am ${user.name},${user.info}`);       // i am ,,,listhello world

    function abc(s, v1, v2) {
        console.log(s, v1, v2);                             // ["i am", ",", "", raw: Array[3]] "list" "hello world"
        return s + v1 + v2
    }
}

{
    console.log(String.raw`Hi\n${1 + 2}`);                  // 对所有\转义
    console.log(`Hi\n${1 + 2}`);
}

5. 数值扩展

{
    console.log('B', 0B111110111);      // 二进制转十进制
    console.log(0o767);                 // 八进制转十进制
}

{
    console.log('15', Number.isFinite(15));             // true,有效数值(非无穷)
    console.log('NaN', Number.isFinite(NaN));           // false
    console.log('1/0', Number.isFinite('true' / 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
    console.log('25.1', Number.isInteger(25.1));        // false
    console.log('25.1', Number.isInteger('25'));        // false
}

{
    console.log(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
    console.log('10', Number.isSafeInteger(10));        // // 是否在正负2^50之间
    console.log('a', Number.isSafeInteger('a'));
}

{
    console.log(4.1, Math.trunc(4.1));                  // 取整数部分
    console.log(4.9, Math.trunc(4.9));
}

{
    console.log('-5', Math.sign(-5));                   // -1
    console.log('0', Math.sign(0));                     // 0
    console.log('5', Math.sign(5));
    console.log('50', Math.sign('50'));                 // 1
    console.log('foo', Math.sign('foo'));               // NaN
}

{
    console.log('-1', Math.cbrt(-1));                   // 立方根
    console.log('8', Math.cbrt(8));
}

6. 数组扩展

{
    let arr = Array.of(3, 4, 7, 9, 11);
    console.log('arr=', arr);

    let empty = Array.of();
    console.log('empty', empty);
}

{
    let p = document.querySelectorAll('p');         // 获取所有p标签
    let pArr = Array.from(p);                       // 把p标签集合转化为数组
    pArr.forEach(function (item) {
        console.log(item.textContent);
    });

    console.log(Array.from([1, 3, 5], function (item) {     // 相当于map()函数
        return item * 2
    }));
}

{
    console.log('fill-7', [1, 'a', undefined].fill(7));         // 把数组元素替换为7
    console.log('fill,pos', ['a', 'b', 'c'].fill(7, 1, 3));     // 从下标为1开始、一直到第3个都替换为7
}

{
    // 需要import Lottery from './lottery';
    for (let index of ['1', 'c', 'ks'].keys()) {            // 获取数组下标
        console.log('keys', index);
    }
    for (let value of ['1', 'c', 'ks'].values()) {          // 获取数组值
        console.log('values', value);
    }
    for (let [index, value] of ['1', 'c', 'ks'].entries()) {        // 相当与python的enumerate
        console.log('values', index, value);
    }
}

{
    console.log([1, 2, 3, 4, 5].copyWithin(0, 3, 4));
}

{
    console.log([1, 2, 3, 4, 5, 6].find(function (item) {           // 查找第一个满足条件的元素
        return item > 3
    }));
    console.log([1, 2, 3, 4, 5, 6].findIndex(function (item) {  
        return item > 3
    }));
}

{
    console.log('number', [1, 2, NaN].includes(1));                 // 判断是否包含元素
    console.log('number', [1, 2, NaN].includes(NaN));
}

7. 函数扩展


// 默认参数
{
    function test(x, y = 'world') {
        console.log('默认值', x, y);
    }

    test('hello');
    test('hello', 'kill');
}
{
    let x = 'test';

    function test2(x, y = x) {
        console.log('作用域', x, y);
    }

    function test3(c, y = x) {
        console.log('作用域', c, y);
    }

    test2('kill');          // kill, kill
    test();                 // undefined, undefined

    test3('kill')           // kill, test
}

// 动态参数
{
    function test3(...arg) {
        for (let v of arg) {
            console.log('rest', v);
        }
    }

    test3(1, 2, 3, 4, 'a');
}

// 扩展运算符
{
    console.log(...[1, 2, 4]);          // 1, 2, 4,把数组拆成三个离散值
    console.log('a', ...[1, 2, 4]);
}


// 箭头函数(匿名函数)
{
    let arrow = v => v * 2;
    let arrow2 = () => 5;               // 无参数时用()
    console.log('arrow', arrow(3));
    console.log(arrow2());

}

// 尾调用(提升性能)
{
    function tail(x) {
        console.log('tail', x);
    }

    function fx(x) {                    // 返回tail函数的调用结果
        return tail(x)
    }

    fx(123)
}

8. 对象扩展

{

    let o = 1;
    let k = 2;

    // ES5对象
    let es5 = {
        o: o,
        k: k
    };

    // ES6对象
    let es6 = {
        o,
        k
    };

    console.log(es5, es6);


    // ES5方法
    let es5_method = {
        hello: function () {
            console.log('hello');
        }
    };

    // ES6方法
    let es6_method = {
        hello() {
            console.log('hello');
        }
    };
    console.log(es5_method.hello(), es6_method.hello());
}

{
    // ES5
    let a = 'b';
    let es5_obj = {
        a: 'c',
        b: 'c'
    };

    // ES6(key可以为变量)
    let es6_obj = {
        [a]: 'c'
    };

    console.log(es5_obj, es6_obj);
}

{

    console.log('字符串', Object.is('abc', 'abc'), 'abc' === 'abc');       // true, true
    console.log('数组', Object.is([], []), [] === []);                     // true, true

    console.log('拷贝', Object.assign({a: 'a'}, {b: 'b'}));                // 两个对象合并成一个(不拷贝继承、不可枚举的属性)

    let test = {k: 123, o: 456};
    for (let [key, value] of Object.entries(test)) {                        // 相当python的items()
        console.log([key, value]);
    }
}

// {
//     // 扩展运算符
//     let {a, b, ...c} = {a: 'test', b: 'kill', c: 'ddd', d: 'ccc'};
//     c = {
//         c: 'ddd',
//         d: 'ccc'
//     }
// }

9. 唯一类型:Symbol

// Symbol:独一无二的值
{
    // 声明
    let a1 = Symbol();
    let a2 = Symbol();
    console.log(a1 === a2);             // false

    let a3 = Symbol.for('a3');          // 类似于“常量池”
    let a4 = Symbol.for('a3');
    console.log(a3 === a4);             // true
}

{
    let a1 = Symbol.for('abc');
    let obj = {
        [a1]: '123',                    // 如a1的值不是Symbol则会报错
        'abc': 345,
        'c': 456
    };
    console.log('obj', obj);            // 则对象中的key有Symbol('123')、'123'和'c'

    for (let [key, value] of Object.entries(obj)) {         // 获取对象中非Symbol属性
        console.log('let of', key, value);
    }

    Object.getOwnPropertySymbols(obj).forEach(function (item) {     // 获取对象中的Symbol属性
        console.log(obj[item]);
    });

    Reflect.ownKeys(obj).forEach(function (item) {          // 获取对象中所有属性
        console.log('ownkeys', item, obj[item]);
    })
}

10. 数据结构Set、Map

// Set
{
    let list = new Set();
    list.add(5);
    list.add(7);
    console.log('size', list.size);     // 2
}
{
    let arr = [1, 2, 3, 4, 5];
    let list = new Set(arr);
    console.log('size', list.size);
}
{
    let list = new Set();
    list.add(1);
    list.add(2);
    list.add(1);
    console.log('list', list);          // [1, 2]

    let arr = [1, 2, 3, 1, '2'];
    let list2 = new Set(arr);
    console.log('unique', list2);       // [1, 2, 3, '2']
}
{
    let arr = ['add', 'delete', 'clear', 'has'];
    let list = new Set(arr);

    console.log('has', list.has('add'));                    // 存在于集合
    console.log('delete', list.delete('add'), list);        // 从集合中删除
    list.clear();
    console.log('list', list);
}
{
    let arr = ['add', 'delete', 'clear', 'has'];
    let list = new Set(arr);

    for (let key of list.keys()) {                          // key和value是一样的
        console.log('keys', key);
    }
    for (let value of list.values()) {
        console.log('value', value);
    }
    for (let [key, value] of list.entries()) {
        console.log('entries', key, value);
    }
    list.forEach(function (item) {
        console.log(item);
    })
}

// WeakSet,元素只能是对象(弱引用,不检测GC),不能遍历
{
    let weakList = new WeakSet();
    let arg = {};

    weakList.add(arg);
    // weakList.add(2);                                     // 不能存放对象以外的值

    console.log('weakList', weakList);
}

// Map
{
    let map = new Map();
    let arr = ['123'];
    map.set(arr, 456);                                      // 注意添加元素方法与Set不同
    console.log('map', map, map.get(arr));
}
{
    let map = new Map([['a', 123], ['b', 456]]);
    console.log('map args', map);                           // Map {"a" => 123, "b" => 456}
    console.log('size', map.size);                          // 2
    console.log('delete', map.delete('a'), map);            // Map {"b" => 456}
    console.log('clear', map.clear(), map);                 // Map {}
    // 遍历方法与Set一样
}

// WeakMap
{
    let weakmap = new WeakMap();

    let o = {};
    weakmap.set(o, 123);
    console.log(weakmap.get(o));
}

// Map、Array对比(增查改删)
{
    let map = new Map();
    let array = [];

    map.set('t', 1);                                // 加入一个key-value
    array.push({t: 1});                             // 加入一个存在t属性为1的元素

    let map_exist = map.has('t');                   // true
    let array_exist = array.find(i => i.t);         // Object {t: 1}

    map.set('t', 2);                                // 把key为t的value修改为2
    array.forEach(i => i.t? i.t = 2: '');           // 先在数组中找到存在t属性的元素,再把它改为2,否则不操作

    map.delete('t');
    let index = array.findIndex(i => i.t);          // 删除存在t属性的元素
    array.splice(index, 1)
}

// Set、Array对比(增查改删)
{
    let set = new Set();
    let array = [];

    set.add({t: 1});
    array.push({t: 1});

    let set_exist = set.has({t: 1});                // 查不到(不能根据对象来查,应该在加入前先保存其引用,通过引用来查)
    let array_exist = array.find(i => i.t);         // Object {t: 1}

    set.forEach(i => i.t? i.t = 2: '');
    array.forEach(i => i.t? i.t = 2: '');           // 先在数组中找到存在t属性的元素,再把它改为2,否则不操作

    set.forEach(i => i.t? set.delete(i): '');       // 遍历,根据值删除
    let index = array.findIndex(i => i.t);          // 删除存在t属性的元素(根据索引)
    array.splice(index, 1)

}

// Map、Set、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;

    let map_exist = map.has('t');
    let set_exist = set.has(item);
    let obj_exist = 't' in obj;

    map.set('t', 2);
    item.t = 2;                     // 对于Set,直接修改所存放的引用,不需要在Set中修改
    obj['t'] = 2;

    map.delete('t');
    set.delete(item);
    delete obj['t'];
}

// 优先使用Map,需确保唯一时使用Set

11. 代理:Proxy和Reflect

// Proxy
{
    
    // 原始对象(存放数据)
    let obj = {
        time: '2017-03-11',
        name: 'net',
        _r: 123
    };

    // 代理对象(存放访问方式)
    let monitor = new Proxy(
        obj,
        {
            // monitor.time,代理对象属性的读取,把从obj取出的time属性值中的2017修改为2018并返回
            get(target, key) {
                return target[key].replace('2017', '2018')
            },
            
            // monitor.name = 'test',代理对象设置属性,只允许修改name属性
            set(target, key, value) {
                if (key === 'name') {
                    return target[key] = value;
                }
                else {
                    return target[key];
                }
            },
            
            // 'name' in monitor,代理key in object操作,只允许访问name属性
            has(target, key) {
                if (key === 'name') {
                    return target[key]
                }
                else {
                    return false;
                }
            },
            
            // delete monitor.name,代理delete
            deleteProperty(target, key) {
                if (key.indexOf('_') > -1) {
                    delete target[key];
                    return true;
                }
                else {
                    return target[key]
                }
            },
            
            // monitor.keys,代理Object.keys, Object.getOwnPropertySymbols, Object.getOwnPropertyNames
            ownKeys(target) {
                return Object.keys(target).filter(item => item != 'time')
            }
        }
    );

    console.log('get', monitor.time);

    monitor.time = '2018';
    monitor.name = 'mukewang';
    console.log('set', monitor.time, monitor);

    console.log('has', 'name' in monitor, 'time' in monitor);

    delete monitor.time;
    console.log('delete',monitor);

    delete monitor._r;
    console.log('delete',monitor);
    console.log('ownKeys', Object.keys(monitor));
}

// Reflect
{
    let obj = {
        time: '2017-03-11',
        name: 'net',
        _r: 123
    };
    console.log('Reflect get', Reflect.get(obj, 'time'));

    Reflect.set(obj, 'name', 'mukewang');
    console.log(obj);
    console.log('has', Reflect.has(obj, 'name'));
}


// 实践
{
    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(`不能设置${key}`);
                    }
                    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);
}

12. 类与对象

{
    // 基本定义和生成实例
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }
    }

    let v_parent = new Parent('v');
    console.log('构造函数和实例', v_parent);
}

{
    // 继承
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }
    }

    class Child extends Parent {
    }

    console.log('继承', new Child());
}

{
    // 继承传递参数
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }
    }

    class Child extends Parent {
        constructor(name = 'child') {
            super(name);
            this.type = 'child';
        }
    }

    console.log('继承传递参数', new Child('hello'));
}

{
    // getter,setter
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }

        get longName() {
            return 'mk' + this.name
        }

        set longName(value) {
            this.name = value;
        }
    }

    let v = new Parent();
    console.log('getter', v.longName);
    v.longName = 'hello';
    console.log('setter', v.longName);
}

{
    // 静态方法
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }

        static tell() {
            console.log('tell');
        }
    }

    Parent.tell();

}

{
    // 静态属性
    class Parent {
        constructor(name = 'mukewang') {
            this.name = name;
        }

        static tell() {
            console.log('tell');
        }
    }

    Parent.type = 'test';

    console.log('静态属性', Parent.type);
}

13. 异步:Promise

{
    // 基本定义
    let ajax = function (callback) {
        console.log('执行');              // 回调:先输出执行,1s后才执行下面的函数
        setTimeout(function () {
            callback && callback.call()
        }, 1000);
    };
    ajax(function () {
        console.log('timeout1');
    })
}

{
    let ajax = function () {
        console.log('执行2');
        return new Promise(
            function (resolve, reject) {
                setTimeout(function () {
                    resolve()
                }, 1000);
            }
        )
    };

    ajax().then(function () {
        console.log('promise', 'timeout2');
        // 使用ajax()返回的对象,执行下一步操作,then的第一个参数即Promise中的resolve
    }, '')
}

{
    let ajax = function () {
        console.log('执行3');
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve()
            }, 1000);
        })
    };

    ajax()          // 执行ajax、再不断指定并执行下一步
        .then(function () {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve()
                }, 2000);
            });
        })
        .then(function () {
            console.log('timeout3');
        })
}

{
    let ajax = function (num) {
        console.log('执行4');
        return new Promise(function (resolve, reject) {
            if (num > 5) {
                resolve()
            }
            else {
                throw new Error('出错了')
            }
        })
    };

    ajax(6)
        .then(function () {
            console.log('log', 6);
        })                              // 执行ajax中的下一步操作
        .catch(function (err) {
            console.log('catch', err);
        });                             // 处理ajax中出现的异常

    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);
            }
        );
    }

    Promise.all([   // 数组所有promise实例视为一个,当所有promise实例发生变化时才会执行then
        loadImg('http://xxxx'),
        loadImg('http://xxx')
        //
    ]).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://xxxx'),
        loadImg('http://xxx')
    ]).then(showImgs)
}

14. 迭代器:iterator

// 使用for...of必须实现iterator接口

{
    let arr = ['hello', 'world'];
    let map = arr[Symbol.iterator]();           // 创建迭代器
    console.log(map.next());
    console.log(map.next());
    console.log(map.next());
}

// 可迭代对象
{
    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() {
                    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)
        console.log('value', value);
}

15. 生成器:generator

{
   // genertaor基本定义
   let tell = function* () {
       yield 'a';
       yield 'b';
       return 'c'
   };

   // 每次调用next时会调用yield之前的语句,然后停止等待下一次调用以此类推
   let k = tell();
   console.log(k.next());
   console.log(k.next());
   console.log(k.next());
   console.log(k.next());
}

// 使用generator实现迭代
{
   let obj = {};
   obj[Symbol.iterator] = function* () {
       yield 1;
       yield 2;
       yield 3;
   };

   for (let value of obj)
       console.log('value', value);

}

// 使用generator实现状态机
{
   let state = function* () {
       while (1) {
           yield 'A';
           yield 'B';
           yield 'C';
       }
   };
   let status = state();
   console.log(status.next());
   console.log(status.next());
   console.log(status.next());
   console.log(status.next());
   console.log(status.next());
}

// {
//     let state = async function () {
//         while (1) {
//             await 'A';
//             await 'B';
//             await 'C';
//         }
//     };
//     let status = state();
//     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.log(`剩余${count}次`);
   };

   let residue = function* (count) {
       while (count > 0) {
           count--;
           yield draw(count);
       }
   };

   let star = residue(5);      // 初始抽奖次数
   let btn = document.createElement('buttot');
   btn.id = 'start';
   btn.textContent = '抽奖';
   document.body.appendChild(btn);
   document
       .getElementById('start')
       .addEventListener('click', function () {
           star.next();
       }, false)
}

// 长轮询(Websocket浏览器兼容性不好)
{
   let ajax = function* () {
       yield new Promise(
           function (resolve, reject) {
               setTimeout(
                   function () {
                       resolve({code: 0})      // 成功后返回{code: 0}
                   }, 200                      // 等待200毫秒
               )
           }
       )
   };

   let pull = function () {
       let generator = ajax();
       let step = generator.next();
       step.value.then(
           function (d) {
               if (d.code != 0)            // 返回状态不为0,则继续轮询,间隔1秒
                   setTimeout(
                       function () {
                           console.log('wait');
                           pull()
                       }, 1000
                   );
               else
                   console.info(d);
           }
       )
   }
}

16. 装饰器:decorator

// 使用装饰器函数扩展类的功能
{
    let readonly = function (target, name, descriptor) {
        descriptor.writable = false;
        return descriptor
    };

    class Test {
        @readonly
        time() {
            return '2017-03-11'
        }
    }

    let test = new Test();

    // test.time=function(){
    //   console.log('reset time');
    // };

    console.log(test.time());
}


{
    let typename = function (target, name, descriptor) {
        target.myname = 'hello';
    };

    @typename
    class Test {

    }

    console.log('类修饰符', Test.myname);
    // 第三方库修饰器的js库:core-decorators; npm install core-decorators
}

// 模拟埋点系统
{
    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('show');
        }

        @log('click')
        click() {
            console.info('click');
        }
    }

    let ad = new AD();
    ad.show();
    ad.click();
}

相关文章

  • ES6

    ES6语法使用总结

  • Vue中es5和es6语法

    https://www.zhihu.com/question/37984203 总结vue中常用的es6语法

  • ES6 JS 类与继承、静态方法

    一 类 ES6以前的语法 console.log("----------------------ES6以前的语法-...

  • ES6 JS 类与继承、静态方法

    一 类 ES6以前的语法 console.log("----------------------ES6以前的语法-...

  • JS数组去重

    1、ES6语法filter()去重 2、ES6语法new Set()去重

  • React基础知识点-ES6基础语法

    ES6语法

  • ES6 语法总结

    1. let,const关键词 2. 结构赋值 3. 正则扩展 4. 字符串扩展 5. 数值扩展 6. 数组扩展 ...

  • ES6语法总结

    摘要 阮一峰《 ECMAScript 6 入门 》 1. Class 1.1 class的定义 上面的代码首先用c...

  • ES6 语法总结

    Arrow Function 箭头函数可以让 this 绑定函数定义时所在的作用域,而不是指向运行时所在的作用域,...

  • ES6小结

    原文链接 es6中有很多特性,使javascript语法更加丰满,总结一波常用的es6知识点。 1.变量声明con...

网友评论

      本文标题:ES6 语法总结

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