es6的学习之路2020

275 阅读5分钟

前言

路漫漫其修远兮,吾之上下而求索

es6的探索之路

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('ad is show')
    }
    @log('click')
    click(){
      console.info('ad is click');
    }
  }

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

Generator

基本使用

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

  let k=tell();

  console.log(k.next());
  console.log(k.next());
  console.log(k.next());
  console.log(k.next());
}

{
  let obj={};
  obj[Symbol.iterator]=function* (){
    yield 1;
    yield 2;
    yield 3;
  }

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

{
  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 txt = document.createElement('p');
txt.innerHTML = '当前抽奖剩余<span id = "count">5</span>次'
document.body.appendChild(txt);

let btn = document.createElement('button');
    btn.id='start';
    btn.textContent ='抽奖';
document.body.appendChild(btn);

//抽奖次数变化
function draw(num){
    let count = document.getElementById('count')
    count.innerHTML = `${num}`
    console.log(`剩余${num}次`)
}

//判断当前是否继续抽奖
function* lottery(num){
    while(num > 0){
        num--;
        yield draw(num)
    }
}

let star = lottery(5) //这里次数由服务端提供接口
document.getElementById('start').addEventListener('click', function(){
      star.next() 
}, false)

长轮询

let ajax = function* () {
yield new Promise((resolve,reject)=>{
    //这里是后端的请求接口
    setTimeout(()=>{
        resolve({code:1})
    })
})
}

let pull = function() {
let generator = ajax();
let step = generator.next();
step.value.then(function(txt){
    if(txt.code!=0){
        setTimeout(()=>{
            console.log('等待更新')
            // pull()
        },2000)
    }else {
        console.log(txt)
    }
})
}
pull()

set-map数据结构篇(优先考虑set map,放弃array,obj)

set的基本用法

//关键 add添加值 size长度
let list = new Set();
list.add(5);
list.add(7);
console.log('size',list.size);//2

//也可以add数组
  let arr = [1,2,3,4,5];
  let list = new Set(arr);
  console.log('size',list.size);//5
  console.log(list);//Set(5) {1, 2, 3, 4, 5}
  
  //set有去重是特性,前提是===
    let list = new Set();
  list.add(1);
  list.add(2);
  list.add(1);
  console.log('list',list);//list Set(2) {1, 2}
  let arr=[1,2,3,1,'2'];
  let list2=new Set(arr);
  console.log('unique',list2);//unique Set(4) {1, 2, 3, "2"}
  
  //has是否有某个值,delete删除,clear清空 
  let arr=['add','delete','clear','has'];
  let list=new Set(arr);
  console.log('has',list.has('add'));//true
  console.log('delete',list.delete('add'),list);//delete true Set(3) {"delete", "clear", "has"}
  list.clear();
  console.log('list',list);//list Set(0) {}

应用场景

  //数组去重    
  let arr=['add','delete','clear','has','clear','has'];
  let arr2 = []
  let list=new Set(arr);

  for(let [key,value] of list.entries()){
    arr2.push(value)
  }
  console.log(arr2)//["add", "delete", "clear", "has"]

WeakSet(1.只能是对象不能是数值,字符串,布尔值等,2.弱引用,不会检测这个对象有没有在其他地方用过,不会跟垃圾回收机制挂钩上)

WeakSet基本使用

let weakList=new WeakSet();
let arg={};
weakList.add(arg);
// weakList.add(2);//报错
console.log('weakList',weakList);//weakList WeakSet {{…}}

Map的基本用法

  // 可以用数组做下标
  let map = new Map();
  let arr=['123'];
  map.set(arr,456);
  console.log('map',map,map.get(arr));//map Map(1) {Array(1) => 456} 456
  
  //map的size、delete和clear差不多
  let map = new Map([['a',123],['b',456]]);
  console.log('map args',map);
  console.log('size',map.size);
  console.log('delete',map.delete('a'),map);
  console.log('clear',map.clear(),map);

WeakMap的基本用法

  //set 设置值,get 获取值
  let weakmap=new WeakMap();
  let o={};
  weakmap.set(o,123);
  console.log(weakmap.get(o));//123

promise篇

promise其实就是一个对象,用来传递异步操作的消息,用promise的好处是代码简洁优雅,方便后期的维护,避免传统回调方式的处理的缺点,我们不知道回调的先后顺序,并且太多回调会让我们掉进回调地狱。

基本使用

传统的方式

  let ajax=function(callback){
    console.log('执行');
    setTimeout(function () {
      callback&&callback.call()
    }, 1000);
  };
  ajax(function(){
    console.log('timeout1');
  })

promise方式

将异步的代码通过return new promise的执行,在异步操作后执行的代码写在then的function里边,第一个function代表resolve,第二个function代表reject

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

  ajax()
    .then(function(){
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 2000);
    });
  })
    .then(function(){
    console.log('timeout3');
  })

应用场景

场景1:连续三个异步操作按顺序执行(我们在开发过程中一定遇到过,第二个接口所请求的参数是第一个接口返回的值吧,有时候甚至第三,第四,第n个接口的参数是根据前面的返回的字段请求,像写一个省市县的三级联动的需求等)

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

  ajax()
    .then(function(){
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 2000);
    });
  })
    .then(function(){
    console.log('timeout3');
  })

场景2:中间某一步出错了,怎么捕获错误

  // 关键:throw new Error和catch
  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);
  }).catch(function(err){
    console.log('catch',err);
  });

  ajax(3).then(function(){
    console.log('log',3);
  }).catch(function(err){
    console.log('catch',err);
  });

场景3:所有图片加载完再添加到页面

 //关键 Promise.all
  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([
    loadImg('https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2714783560,2670973992&fm=26&gp=0.jpg'),
    loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
    loadImg('https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4171635295,1860398794&fm=26&gp=0.jpg')
  ]).then(showImgs)

场景4:有一个图片加载完就添加到页面(常用的场景还有倒计时,异步操作和定时器放到一起,如果定时器先触发,认为超时,告知用户)

// 关键 Promise.race
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://i4.buimg.com/567571/df1ef0720bea6832.png'),
    loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
    loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs)

Module模块化

基本使用

export导出

/*导出的文件testExport.js*/

/*第一种 分别导出*/
 export let A=123;

 export function test(){
  console.log('test');
 }

 export class Hello{
   test(){
    console.log('class');
  }
}


/*第二种 以一个对象的形式导出*/
let A=123;
let test=function(){
  console.log('test');
}
class Hello{
  test(){
    console.log('class');
  }
}

export default {
  A,
  test,
  Hello
}

import引入

/*导入的文件testImport.js*/

// 第一种,必须和export的名称完全一致
import {  A,test,Hello} from testExport.js

// 第二种,以对象形式import
import dataExport from testExport.js

let a = dataExport.A
console.log(a);//123

推荐大家使用第二种方法啦,可以根据自己的需要起不同的名字取值,而且导出的时候也可以少写一些代码