• ES6学习笔记


    一、let、const、块作用域

    let-cont相同点:
    1.强制使用严格模式;
    2.不能重复声明同意变量。
    3.都能在 {} 块作用域中生效;(即作用域范围是:{} )
    const:
    1.声明5中基本类型之后,便不能修改值;但是声明变量,则存储的是对象的内存地址。
    2.初始化时,必须赋值。

    二、解构赋值 :对象和数组

    共同点:
    1.无匹配时返回undefined;
    2.可以设置默认值;
    3.优先级:赋值 > 设置的默认值 .> 无匹配时的undefined
    数组解构:

    let [a, b, ...c] = [1,2,3,4];  // a=1,b=2,c=[3,4]

    应用场景:(数组值的对换)

    let a = 1;
    let b = 2;
    
    [a, b] = [b, a];  //a=2,b=1

    对象解构:重命名的name写在对象的value中;

    let data = {
        title: 'abc',
        list: [
            {
                title: 'test...',
                des: 'des...'
            }
        ]
    }
    
    //拿到 第一层的title和第二层的title
    let {title,list: [{title: cnTitle}]} = data;  //title='abc',cnTitle='test...'

    三、正则的拓展

    构造函数的拓展:

    1.可以在构造函数的1参和2参添加修饰符;2参>1参(2参会覆盖1参)

    2.reg.flags :修饰符的查询;(其中reg是一个正则的实例)

    let r1 = new RegExp(/a/);
    let r2 = new RegExp(/a/i);
    let r3 = new RegExp(/a/i, 'g');
    let str1 = 'AbcAd';
    console.log( r1.test(str1), r1.flags );  //false ''
    console.log( r2.test(str1), r2.flags );  //true  'i'
    console.log( r3.test(str1), r3.flags );  //false 'g'  [产生了覆盖]

    y修饰符: 更加严格的匹配,第一次和第二次匹配中间不能有任何的间隔。

    1. reg.sticky: 是否使用y修饰符。
    let r1 = /a/i;
    let r2 = /a/iy;
    
    let s1 = 'AbAc';
    let s2 = 'AAc';
    
    console.log(r1.test(s1), r1.sticky); //true false
    console.log(r2.test(s1), r2.sticky); //true true
    console.log(r1.test(s1), r1.sticky); //true false
    console.log(r2.test(s1), r2.sticky); //false true  [匹配更加严格,中间不能有任何间隙]
    
    console.log(r1.test(s2 ), r1.sticky); //true false
    console.log(r2.test(s2 ), r2.sticky); //true true
    console.log(r1.test(s2 ), r1.sticky); //true false
    console.log(r2.test(s2 ), r2.sticky); //true true  [中间没有任何间隙]

    [补充]:字符的定义:字符是指计算机中使用的字母、数字、字和符号

    在 ASCII 编码中,一个英文字母字符存储需要1个字节。在 GB 2312 编码或 GBK 编码中,一个汉字字符存储需要2个字节。在UTF-8编码中,一个英文字母字符存储需要1个字节,一个汉字字符储存需要3到4个字节。在UTF-16编码中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。在UTF-32编码中,世界上任何字符的存储都需要4个字节。

    [补充]:1字符 == 2字节 == 4个十六进制字母

    let a = '稳';
    let b = a.charCodeAt(0);  //转unicode编码
    let c = b.toString(16);   //将unicode编码转十六进制
    
    console.log(b, c);  //31283    '7a33'    “稳”字的unicode码,十六进制
    console.log( b.fromCharCode(b) );  //稳
    console.log( b.fromCharCode('0x'+c) );  //稳

    在Unicode编码下的例子:
    稳(1字符) == 2字节 [7a,33] == 4个十六进制字符[7,a,3,3]

    u修饰符:匹配unicode字符,处理大于2字节长度的字符。
    下面乱码的字符是 ,unicode十六进制是:20bb7,可以使用 String.fromCodePoint('0x20bb7') 方法转回字符(此方法为ES6方法)

    let a = '?'; //unicode码字符大于4字节
    let b = a.codePointAt(0);  //134071
    let c= b.toString(16);  //20bb7
    
    console.log( /u{20bb7}/.test('?') );  //false
    console.log( /u{20bb7}/u.test('?') )  //true

    s修饰符: s修饰符,可以使 点(.)匹配 字符
    正则中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符除外:

    // U+000A 换行符(
    )
    
    // U+000D 回车符(
    )
    
    // U+2028 行分隔符(line separator)
    
    // U+2029 段分隔符(paragraph separator)
    

    只是一个提案目前还不支持,es8中实现

        let r1=/test.go/s;
        let r2=/test.go/;
    
        let s = 'test
    go';
        console.log(r1.test(s));  //true
        console.log(r2.test(s));  //false

    四、字符串的拓展

    下面乱码的字符是 ,unicode十六进制是:20bb7,可以使用 String.fromCodePoint('0x20bb7') 方法转回字符(此方法为ES6方法)

    [补充]:.length属性: 计算长度时,每2个字节为一个字符。

    let a = '稳';
    let b = String.fromCodePoint('0x20bb7');
    
    console.log(a.length);  // 1
    console.log(b.length);  // 2

    [补充]:ES5转码方法介绍: (只能转<=2个字节的字符)

    1. str.charAt(0) 返回第0位的字符;

    2. str.charCodeAt(0) 返回第0位字符的Unicode编码,可以使用.toString(16)转16进制;

    3. String.fromCharCode() 将Unicode编码转字符串,十六进制转法:str.fromCharCode('0x'+'7a33')

    let str = '稳';
    
    console.log( str.charAt(0) );    //稳
    console.log( str.charCodeAt(0) );    // 31283
    console.log( String.fromCharCode(31283) )  //稳

    ES6转码方法介绍: (可以转> || <= 2个字节的字符)

    1. str.codePointAt(0) 将第0位转Unicode吗

    2. str.fromCodePoint() 将Unicode码转字符串

    3. for...of —> 可以正确的解析 > || <= 2字节的字符。

    let @a = String.fromCodePoint('0x20bb7');  //@a 即上面几例中的乱码字符,使用这个方法就可以得到这个字符
    let a = @a.charCodeAt(0);    //31283
    let b = @a.codePointAt(0); //134071
    
    String.fromCharCode(a);   //String.fromCodePoint(b);  // @a  ---> 这里代指 @a表示的字符,因为这个编辑器输出这个字符会乱码

    字符串的检测:

    1.str.includes('s') —> str中是否包含s

    2.str.startWith('st') —>str是否以st开头

    1. str.endWith('ing') —> str中是否以ing结尾
    let s = 'string';
    
    console.log( s.includes('tr') )  //ture
    console.log( s.includes('ti') )  //false  [测试不连续的字符]
    
    console.log( s.startsWith('st') )  //true
    console.log( s.startsWith('sr') )  //false [测试不连续的字符]
    
    console.log( s.endsWith('ing') )  //true
    console.log( s.endsWith('ig') )   //false  [测试不连续的字符]

    模板字符串:
    1.

    let str = 'david';
    `I am ${str}`  // I am david  为变量
      2.
    function add(){
        console.log(arguments);
    }
    let user = {
        name: 'david',
        info: 'man'
    }
    add`I am ${user.name},${user.info}`
    
    //arguments --->  ['I am ',',',''] 'david' 'man'

    补位:(ES7)指定长度2,不够的补’0’

    1.'1'.padStart(2,'0') —> 输出为:’01’

    2.'1'.padEnd(2,'0') —> 输出为:’10’

    let s1 = '1';
    let s2 = '1.';
    
    s1.padStart(3, '');  // '1'
    s1.padStart(1, '0'); // '1'
    s1.padStart(2, '0'); // '01'
    
    s2.padEnd(2, '0');  // '1.'
    s2.padEnd(3, '0');  // '1.0'

    五、数值的拓展

    [补充]:二进制<—>十进制、八进制<—>十进制 的相互转化:

    let a = 20;
    let b = a.toString(2);   // 10100  {二进制}
    let c = parseInt(b, 2);  // 20     {十进制}
    
    let d = a.toStrging(8);  // 24     {八进制}
    let e = parseInt(d, 8);  // 20     {十进制}

    二进制和八进制的表示方法:

    0b 或者 0B表示二进制

    0o 或者 0O 表示八进制

    console.log( 0b10100 )  // 20  输出的时候会被转成10进制
    console.log( 0o24 )     // 20

    Number对象的属性和方法:

    Number.MAX_SAFE_INTEGER –> 最大 的安全整数

    Number.MIN_SAFE_INTEGER –> 最小 的安全整数

    Number.isInteger(number)· –> 是一个整数? {无类型转换} true(是);false(不是)

    Number.isSafeInteger(number) –> 是一个安全的整数? {无类型转换} true(是);false(不是)

    console.log( Number.isInteger(10) )  //true
    console.log( Number.isInteger(10.1) )//false
    
    console.log( Number.isSafeInteger(10) )    //true
    console.log( Number.isSafeInteger(10.1) ); //false
    
    console.log( Number.MAX_SAFE_INTEGER )  //9007199254740991
    console.log( Number.MIN_SAFE_INTEGER )  //-9007199254740991

    Math对象的方法:

    Math.trunc(Number) –> 取整 ; [-1,0,1,Infinity,NaN]

    Math.sign(number) –> 判断正负 [1,0,-1,NaN]

    Math.cbrt(number) –> 立方根

    console.log( Math.trunc(1.1) )        //1
    console.log( Math.trunc(-2.1) )       //-2
    console.log( Math.trunc(Infinity) )   //Infinity
    console.log( Math.trunc(NaN) )        //NaN
    
    console.log( Math.sign(1.1) )         //1
    console.log( Math.sign(-1.1) )        //-1
    console.log( Math.sign(0) )           //0
    console.log( Math.sign(Infinity) )    //1
    console.log( Math.sign(NaN) )         //NaN
    
    console.log( Math.cbrt(8) )           //2

    六、数组的拓展

    创建:

    Array.of(1) –> 将传入的集合创建为数组;主要是弥补new Array(1),这个方法的缺项。

    Array.from(arguments) –> 将伪数组转为数组

    修改:

    [1,2,3,4].fill(1,3,4) –> 将1填充进数组第3位到第4位(不含第四位)

    [1,2,3,4,5,6].copyWithin(0,1,3) –> 取第1-3(不含)位: 2,3 替换 1,2; 最后结果为:[2,3,3,4,5,6]

    function add(){
        let arr = Array.from(arguments);
        console.log( Object.prototype.toString.call(arguments) )  // [object Aguments]
        console.log( Object.prototype.toString.call(arr) )        // [object Array]
        console.log(arr)    // 1,2,3,4,5
        arr.fill(1,3,4);
        console.log(arr)    // 1,2,1,4,5 
        arr.fill(1,3,5);
        console.log(arr)    // 1,2,1,1,5
    }
    add(1,2,3,4,5)
    
    console.log( [1,2,3,4,5,6,7,8].copyWithin(0, 1, 3) )  //[4, 5, 3, 4, 5, 6, 7, 8]

    遍历:
    1.数组:

    [1,2,3].keys() –> 遍历键

    [1,2,3].values() –>遍历值

    [1,2,3].entries() –>遍历键值

    2.对象:

    Object.keys(obj) –>遍历键

    Object.values(obj) –>遍历值

    Object.entries(obj)–>遍历键值

    let a = [1,2,3,4];
    let b = {
        a: 1,
        b: 2,
        c: 3,
        d: 4
    }
    
    for( let k of a.keys()){
        console.log( k )  // 0,1,2,3
    }
    for( let v of a.values()){
        console.log( v )  // 1,2,3,4
    }
    for( let [k, v] of a.entries()){
        console.log( k, v)  // [0,1],[1,2],[2,3],[3,4]
    }
    
    for(let k of Object.keys(b)){
        console.log( k )  //a,b,c,d
    }
    for(let v of Object.values(b)){
        console.log( v )  //1,2,3,4
    }
    for(let [k, v] of Object.entries(b)){
        console.log( k, v )  //[a,1],[b,2],[c,3],[d,4]
    }

    检测:

    [1,2,3].find(callback(item,index)) –> 找到符合条件的值,只返回第一个

    [1,2,3].findIndex(callback(item,index)) –> 找到符合条件的值的下标,只返回第一个

    [1,2,NaN].includes(NaN) –> 检测数组是否有这个值,检测NaN返回true

    console.log( [1,2,3,4].find((item,index)=>item>2&&index!=2) )  //4
    console.log( [1,2,3,4].findIndex((item,index)=>item>2) )       //2
    
    console.log( [1,2,3,NaN].includes(NaN) )  //true
    console.log( [1,2,3,2,NaN].includes(2) )  //true

    七、函数的拓展

    箭头函数:三种写法

    let add = (x,y)=>{return x+y;} —> //常规写法

    let add = x=>{return x+y;} —> //一个参数时,可以省略 ()

    let add = x=>x+y —> // 函数体只有一句话时,可以省略 {},默认将x+y作为返回值

    优势:
    1.解决了this的指向问题;
    2.写法更加简洁。

    参数默认值:

    let add = (x=1,y=2)=>x+y —> // 给x,y设置了默认参数1,2

    rest/spread参数:

    //rest
    function add(a, ...b){
        console.log(a)  // 1
        console.log(b)  // [2,3,4]
    }
    add(1,2,3,4,5);
    
    //spread
    let c = [1,2,3,4];
    function add2(a,b,c){
        console.log(a,b,c)   // 1,2,3
        console.log(arguments[3]) // 4
    }
    add2(...c);

    函数的尾调用:提升性能
    在函数结束的return后跟一个函数调用

    function b(){ return c(); }
    function c(){};

    八、对象的拓展

    对象简写模式:属性和方法

    let obj = {a,add(){}},a:属性名是a,属性值是:变量a;add:表示一个函数。

    对象属性表达式:属性名是一个可变的值。

    新增API:

    Object.is(a,b) ,判断a===b? true : false 可以判断NaN

    Object.assign(a,b,c) c覆盖b,b覆盖a,保留a有,b c没有。

    Object.entries(obj) 遍历key和value

    Object.keys() 遍历key

    Object.values()遍历value

    let a = 1;
    let b = {
        name: 'bb'
    }
    let c = [1,2,3];
    let d = 'dd';
    let e = b;
    let o1 = {
        a,
        b,
        c,
        [d]: 'dd'
    }
    let o2 = {
        a: '11',
        b: '22'
    }
    let o3 = {
        b: '222',
        c: '333'
    }
    
    console.log( o1 )
    /*
    {
        a: 1,
        b: {name: "bb"},
        c: [1, 2, 3],
        d: "dd"
    }
    */
    
    console.log( o1[d] )  // dd
    console.log( o1.dd )  // dd
    
    
    console.log( Object.is(1, '1') );  //false  [全等]
    console.log( Object.is(NaN, NaN) );  //true
    console.log( Object.is(b, e) );  //true
    
    
    // 1.浅拷贝:复制基本类型的值,复制对象类型的内存地址
    // 2,后面覆盖前面对象的值,但是保留后面对象没有的值
    let f = {
        a: '1111'
    };
    Object.assign(f, o2, o3);  
    console.log( f )
    /*
    {
        a: '11',
        b: '222',
        c: '333'
    }
    */
    
    console.log(Object.entries(f))  //[['a','11'],['b','222'],['c','333']]
    console.log(Object.keys(f))  //['a','b','c']
    console.log(Object.values(f))  //['11','222','333']

    九、Symbol: [创建独一无二的值]

    创建:Symbol.for('aa')

    API:

    Object.getOwnpropertySymbols(obj)数组返回obj中所有的Symbol 属性

    Reflect.ownKeys(obj)数组返回obj中所有的普通属性和Symbol 属性

    let a = Symbol.for('aa')
    let b = Symbol.for('bb')
    
    let o = {
        [a]: 1,
        aa: 2,
        [b]: 3
    }
    
    console.log(o)
    /*
    {
        aa: 2,
        Symbol(aa): 1
    } 
    */
    console.log( o[a] )  // 1
    
    //Symbol不能被for...in遍历
    for(let i in o){
        console.log(i)  //[aa]
    }
    
    console.log( Reflect.ownKeys(o) );  // ['aa', Symbol(aa), Symbol(bb)]
    
    console.log( Object.getOwnPropertySymbols(o) );  // [Symbol(aa), Symbol(bb)]
    
    

    十、数据解构

    Set数据解构:类似数组集合 [‘不能出现重复的数据’]

    let arr1 = [1,2,3,4];
    let obj1 = {
        a: 11,
        b: 22
    }
    let s1 = new Set(arr1);  // Set(4) {1,2,3,4}
    
    //增
    s1.add(NaN);  // Set(4) {1,2,3,4,5}
    s1.add(1);    // Set(4) {1,2,3,4,5}
    
    //查
    s1.has(NaN);  //true
    s1.has(0);    //false
    
    //删
    s1.delete(NaN) // Set(4) {1,2,3,4}
    s1.clear();    // Set(0) {}
    
    //遍历
    s1 = new Set(arr1);
    for(let [k, v] of s1.entries()){
        console.log( k, v )  //[[1,1], [2,2], [3,3], [4,4]]
    }
    for(let k of s1.keys()){
        console.log( k)  //[1,2,3,4]
    }
    for(let v of s1.values()){
        console.log( v )  //[1,2,3,4]
    }
    for(let value of s1){
        console.log(value);  //[1,2,3,4]
    }
    s1.forEach((item, i)=>{
        console.log( item, i )  //[[1,1], [2,2], [3,3], [4,4]]
    })

    WeakSet数据结构:

    WeakSet和Set的区别:

    // 1:支持的数据类型不一样,WeakSet的元素只能是对象
    // 2:WeakSet的元素对象是个弱引用,只是个地址,不会检测这个地址是否被垃圾回收机制回收掉了
    // 3:没有size属性,也不能使用clear
    // 4:无法遍历

    Map数据结构:类似对象 [‘可以使用对象作为属性名’]

    let a = [1,2,3];
    let o = {
        a: 11,
        b: 22
    }
    let c = 'qwe';
    let m = new Map();
    
    //增
    m.set('a', a).set('o', o).set('c', c)  //添加成功  可以理解为:{a: [1,2,3], o: {a: 11, b: 22}, c: 'qwe'};
    
    //查
    m.has('a')  // true
    
    //改
    m.set('a', 'aa');  //aa
    
    //删
    m.delete('a');
    m.clear();
    
    m.set('a', a).set('o', o).set('c', c);
    //遍历
    for(let [k, v] of m.entries()){
        console.log(k, v);  // [ ['a',[1,2,3]], ['o', {a: 11, b: 22}], ['c', 'qwe'] ]
    }
    for(let k of m.keys()){
        console.log(k)  // [ 'a', 'o', 'c' ]
    }
    for(let v of m.values()){
        console.log(v)  // [ [1,2,3], {a: 11, b: 22}, 'qwe' ]
    }
    m.forEach((v, k)=> {console.log('forEach', v , k);})  //[ [[1,2,3],'a'], [{a: 11, b: 22}, 'o'], ['qwe', 'c'] ];

    WeakMap数据结构:

    // WeakMap和Map的区别:

    // 1:支持的数据类型不一样,WeakMap的元素只能是对象
    // 2:WeakMap的元素对象是个弱引用,只是个地址,不会检测这个地址是否被垃圾回收机制回收掉了
    // 3:没有size属性,也不能使用clear
    // 4:无法遍历

    十一、数据结构的对比

    结论:优先使用map,能使用map就使用map,不使用数组,object; 考虑数据存储的唯一性,则使用set

    {
      //数据结构横向对比,map和数组的对比,增删改查
      let map=new Map();
      let array=[];
      //增
      map.set('a',1);
      array.push({'a':1});
      console.log('map-array-insert',map,array); // map-array Map {"a" => 1} [Object]
      //查
      let map_exist=map.has('a');
      let array_exist=array.find(item=>item.a);  //返回item.a
      console.log('map-array-exist',map_exist,array_exist);//map-array-exist true Object {a: 1}
      //改
      map.set('a',2);
      array.forEach(item=>item.a?item.a=2:'');//遍历每个item,判断key为a的item是否存在,存在则改
      console.log('map-array-update',map,array); 
      //删
      map.delete('a');
      let index=array.findIndex(item=>item.a);
      array.splice(index,1);
      console.log('map-array-delete',map,array); // map-array-delete Map {} []
    }
    
    {
      //数据结构横向对比,Set和数组的对比,增删改查
      let set=new Set();
      let arr=[];
    
      //增
      set.add({t:1});
      arr.push({t:1});
      console.log('set-array-insert',set,arr); //set-array-insert Set {Object {t: 1}} [Object]
    
      //查
      let set_exist=set.has({t:1});
      let arr_exist=arr.find(item=>item.t);  //返回item.a
      console.log('set-array-exist',set_exist,arr_exist);//set-array-exist false Object {t: 1}
    
      //改
      set.forEach(item=>item.t?item.t=2:'');
      arr.forEach(item=>item.t?item.t=2:'');//遍历每个item,判断key为a的item是否存在,存在则改
      console.log('set-array-update',set,arr);  //set-array-update Set {Object {t: 2}} [Object]
    
      //删
      set.forEach(item=>item.t?set.delete(item):'');
      let index=arr.findIndex(item=>item.t);
      arr.splice(index,1);
      console.log('set-array-delete',set,arr); // set-array-delete Set {} []
    
    }
    
    {
      // set,map,object对比
      let item={t:1};
      let set=new Set();
      let map=new Map();
      let obj={};
    
      //增
      set.add(item);
      map.set('t',1);
      obj['t']=1;
      console.log("set-map-obj",set,map,obj);//set-map-obj Set {Object {t: 1}} Map {"t" => 1} Object {t: 1}
    
      //查
      console.log({
        'set-exist':set.has(item),
        'map-exist':map.has('t'),
        'obj-exist':'t' in obj
      });  // Object {set-exist: true, map-exist: true, obj-exist: true}
    
      //改
      item.t=2; //set元素的修改,因为存储的是地址
      map.set('t',2);
      obj['t']=2;
      console.log("set-map-obj-update",set,map,obj); // set-map-obj-update Set {Object {t: 2}} Map {"t" => 2} Object {t: 2}
    
      //删
      set.delete(item);
      map.delete('t');
      delete obj['t'];
      console.log("set-map-obj-delete",set,map,obj); // set-map-obj-delete Set {} Map {} Object {}
    }

    十二、Proxy:代理对象、Reflect:映射

    Proxy:

    get(target, key){}

    set(target, key, value){}

    deleteProperty(target, key){}

    has(target, key){}

    ownKeys(target, key){}

    let obj = {
        name: 'obj',
        time: '2018',
        age: 24
    }
    
    let proxy = new Proxy(obj, {
        get(target, key){
            if(key === 'age'){
                return 0;
            }else{
                return target[key];
            }
        },
        set(target, key, value){
            if(key === 'age'){
                return target[key];
            }else{
                return target[key] = value;
            }
        },
        //拦截for...in
        has(target, key){
            if(key === 'age'){
                return false;
            }else{
                return target[key];
            }
        },
        deleteProperty(target, key){
            if(key === 'age'){
                delete target[key];
                return true;
            }else{
                return target[key];
            }
        },
        // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
        ownKeys(target){   //只能获取属性不为time的属性
          return Object.keys(target).filter(item=>item!='age')
        }
    })
    
    console.log( proxy.name, proxy.age )  // obj 0
    
    proxy.name = 'obj1';  //修改成功
    proxy.age = 0;        //修改失败
    
    console.log( 'name' in proxy ) // true
    console.log( 'age' in proxy )  // false
    
    delete proxy.name;  //删除成功
    delete proxy.age;   //删除失败
    
    console.log( Object.keys(proxy) ) // [ 'name', 'time' ]
    

    Reflect:

    Reflect.get(obj, 'name')

    Reflect.set(obj, 'age', 0)

    Reflect.deleteProperty(obj, 'age')

    Reflect.ownKeys(obj)

    let obj = {
        name: 'obj',
        time: '2018',
        age: 24
    }
    
    let obj = {
        name: 'obj',
        time: '2018',
        age: 24
    }
    
    console.log( Reflect.get(obj, 'name') )  //obj
    Reflect.set(obj, 'age', 0)  //修改成功:age: 0
    console.log( Reflect.has(obj, 'time') )  //true
    Reflect.deleteProperty(obj, 'age');  //删除成功
    console.log( Reflect.ownKeys(obj) )  //['name', 'time']

    十三、类和实例

    1.构造函数:constructor(){} 实例化时,会执行的函数。
    2.继承的关键字:extends
    3.子类继承时,必须调用:super
    4.定义变量获取/设置方式:get className(){}set className(){}
    5.静态方法: static tell() {}
    6.静态属性: [className].type = 'class'className是类名

    class Person {
        constructor(x=1, y = 2){
            this.x = x;
            this.y = y;
            this.name = 'david'
        }
        get longName(){
            return '1 ' + this.name;
        }
        set longName(val){
            this.name = val;
        }
        static add (){
            console.log(111);
        }
    }
    let p = new Person();
    p.longName;  // '1 daivd'
    p.longName = 11; // 11
    
    
    class Son extends Person{
        constructor(x, y){
            super(x,y)
        }
    }
    Person.type = 'class';
    Person.add();  // 111
    Person.type;   // class
    let s = new Son(8, 9);  //{x: 8, y: 9}

    十四、异步编程:Promise对象

    详细讲解请看另一篇文章:8个例子学会Promise

    promise.all([fn1, fn2, fn3]) //其中fn1fn2fn3的所的resolve()之后,执行then()
    promise.rece([fn1, fn2, fn3])//其中fn1fn2fn3有一个resolve(),就执行then()

    {
      //功能:所有的图片都加载完后再添加到页面里
    
      //加载图片
      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实例,当这些实例的状态都发生改变时
      //才会返回一个新的promise实例,才会执行then方法
      Promise.all([
        loadImg("http://i4.buimg.com/567571/df1ef0720bea6832.png"),
        loadImg("https://ss1.baidu.com/9vo3dSag_xI4khGko9WTAnF6hhy/imgad/pic/item/6f061d950a7b0208b8265dea6ad9f2d3562cc8ca.jpg"),
        loadImg("https://ss1.baidu.com/9vo3dSag_xI4khGko9WTAnF6hhy/imgad/pic/item/9f510fb30f2442a750999faed943ad4bd1130221.jpg")
      ]).then(showImgs);
    
    }

    十五、自定义接口:Symbol.iterator,for…of遍历使用的就是Symbol.iterator接口

    Symbol.iterator 在对象中自定义itetator接口,然后使用for…of遍历

    //数组
    let arr = ['a', 'b', 'c'];
    let map = arr[Symbol.iterator](); // 数组内部已经实现了Symbol.iterator接口
    //arr[Symbol.iterator]会返回一个遍历的函数,再()一下执行这个函数,会返回一个对象
    console.log( arr[Symbol.iterator] )  //ƒ values() { [native code] }
    
    // // map.next()先返回第一个值,如果还有下一个值,则done为false
    console.log( map.next() )  // {value: "a", done: false}
    console.log( map.next() )  // {value: "b", done: false}
    console.log( map.next() )  // {value: "c", done: false}
    console.log( map.next() )  // {value: undefined, done: true}
    
    
    
    
    //对象:自定义iterator接口,for...of循环使用的就是内部的Symbol.iterator接口遍历
    let obj = {
        start: [1,2,3],
        end: [4,5,6]
        [Symbol.iterator](){
            let self = this,
            arr = self.start.concat(self.end),
            index = 0,
            len = arr.length;
    
            return {
                next(){
                    if(index < len){
                        return {
                            value: arr[index++],
                            done: false
                        }
                    }else{
                        return {
                            value: arr[index++],
                            done: true
                        }
                    }
                }
            }
        }
    }

    十六、异步编程:Generator函数、async是Gnerator函数的语法糖

    Generator也是异步编程的一种解决方案。比promise更高级。

    定义:function* (){}

    关键字:yield

    实践:

      let tell=function* (){  // function加*
          yield 'a';
          yield 'b';
          return 'c';
      }
      let k=tell();  //调用tell时遇到yield会停下来
      //调用next时会执行第一个yield
      console.log(k.next()); // Object {value: "a", done: false}
      console.log(k.next()); // Object {value: "b", done: false}
      console.log(k.next()); // Object {value: "c", done: true}
      console.log(k.next()); // Object {value: "undefined", done: true}
      //Generator返回的就是一个Iterator接口

    让对象也可以遍历,Generator就是一个遍历器生成函数:

    {
      let obj={};
      obj[Symbol.iterator]=function* (){
        yield 1;
        yield 2;
        yield 3;
      }
    
      for(let value of obj){
        console.log('value',value);  
        // value 1
        // value 2
        // value 3
      }
    }

    状态机:

    {
      //状态机,只存在三种状态(A,B,C)   (A->B->C->A->B....一直循环)
       let state=function* (){
        while(1){
          yield 'A';
          yield 'B';
          yield 'C';
        }
      }
      let status=state();
      console.log(status.next()); // Object {value: "A", done: false}                    
      console.log(status.next()); // Object {value: "B", done: false}
      console.log(status.next()); // Object {value: "C", done: false}
      console.log(status.next()); // Object {value: "A", done: false}
      console.log(status.next()); // Object {value: "B", done: false}
    }

    async:

    {
      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 ajax=function* (){
        yield new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve({code:0});
            },2000);
        });
      }
    
      let pull=function(){
        let genertaor=ajax();
        let step=genertaor.next();
        step.value.then(function(d){  //这里的d就是上面的{code:0}
          if(d.code!=0){
            setTimeout(function(){
               console.log('wait');
               pull(); 
            });
          }else{
            console.log(d);
          }
        })
      }
    
      pull();

    十七、Decorator:修饰器 [作用于函数,修改行为,修改函数的行为]

    需要babel导入下面的插件才能使用decorator:babel-plugin-transform-decorators-legacy

    descripttor的使用:

      //定义一个decorator函数,target是要修改的类,name是要修改的类的属性名称,
      //descriptor是这个属性的描述,是一个对象
      let readonly=function(target,name,descriptor){
        console.log(descriptor); 
        // Object {writable: true, enumerable: false, configurable: true,value:function(){}}
        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());  //2017-03-11

    * target的使用: *

      let typename=function(target,name,descriptor){
        target.myname='hello';  //设置类的属性
      }
    
      @typename
      class Test{
    
      }
    
      console.log('类修饰符',Test.myname);  // 类修饰符 hello
      // 第三方库修饰器的js库:core-decorators; npm install core-decorators
     //这里之所以要用箭头函数,是因为要接收@log的参数
      let log=(type)=>{
        return function(target,name,descriptor){
          console.log(descriptor); 
          // Object {writable: true, enumerable: false, configurable: true,value:function(){}}
    
          let src_method=descriptor.value; //获取被修饰的方法
          console.log(src_method);  
          // show(){
          //   console.info('ad is show');
          // }
    
          //修改方法的行为
          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();

    十八、模块化

    模块导入导出:

    import {a,b,c} from '***'export b; export a;exprot c;

    import * as all from '***' 其中 all为别名

    import a from '***'export default {name: 'a'}

  • 相关阅读:
    Linux学习32
    Linux学习31-如何查看 linux 系统是centos还是ubuntu,并查看系统版本号
    python测试开发django-124.bootstrap点删除按钮弹确认删除
    python测试开发django-123.bootstrap模态框(modal)垂直居中显示
    python测试开发django-122.bootstrap模态框(modal)学习
    Linux下查询tomcat进程命令
    linux服务器通过X11实现图形化界面显示 1 背景描述
    linux(centos)配置ipv6网卡
    linux 下给网卡添加ipv6、路由
    2021年最新大厂php+go面试题集(1)
  • 原文地址:https://www.cnblogs.com/wenwenwei/p/10017850.html
Copyright © 2020-2023  润新知