ES6入门(Proxy和Reflect,类和对象,Promise,Lterator,Genertor,Decorators,模块化)

Proxy和Reflect(反射)

方法一模一样

Coca-cola供货商(压缩汽水)->包装(Proxy),兑水(读get),吐唾沫(has),偷喝(deleteProperty),添加各种口味(操作set)->出货

{
  let obj={
    time:'2017-03-11',
    name:'net',
    _r:123
  };

  let monitor=new Proxy(obj,{
    // 拦截对象属性的读取
    get(target,key){
      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
    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'));
}

Proxy和Reflect使用场景

数据校验

传统方式:在赋值时进行判断
把业务逻辑和对象本身隔离开

{
  function validator(target,validator){
    return new Proxy(target,{
      _validator:validator,
      set(target,key,value,proxy){
        // 判断是否有KEY
        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('wangchunlong',30);

  console.info(person); 

  person.name="wangwangwang";

  console.info(person); 
}

类和对象

  • 基本语法
  • 类的继承
  • 静态方法
  • 静态属性
  • getter
  • setter
基本语法
{
  // 基本定义和生成实例
  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(属性,不是方法)
{
  // 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;
    }
  }

  Parent.type='test';

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


}

Promise(异步操作)

实现异步的两种方式(ES5):回调,事件触发

“同步模式”就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;”异步模式”则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

ES5回调异步

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

很难阅读,代码复杂,可维护性差

Promise
{
  let ajax=function(){
    console.log('执行2');
    return new Promise(function(resolve,reject){
        // 具有了一个then的方法
        // resolve 执行下一步的操作
        // reject 中断当前的操作
      setTimeout(function () {
        resolve()
      }, 1000);
    })
  };

  ajax().then(function(){
    console.log('promise','timeout2');
  })
}
{
  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');
  })
}
Promise捕获异常
{
  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);
  });
}
Promise实用场景

今日头条首页推荐流(图片全部加载完,才呈现在页面上,提高用户体验)

{

  //  加载图片
  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.all([
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.jpg'),
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.jpg'),
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.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){
    document.body.appendChild(img);
  }

// Promise.race 有一个状态改变,race的状态也会跟着改变,其他不再响应
  Promise.race([
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.jpg'),
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.jpg'),
    loadImg('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498142965451&di=846cd76e25cb0d159b91c57ab615290f&imgtype=jpg&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D1823136043%2C1469760399%26fm%3D214%26gp%3D0.jpg')
    ]).then(showImgs)
}

Lterator

用法:不同数据结构的集合如何统一读取
for of循环的过程就是不断调用Lterator接口的过程

{
  let arr=['hello','world'];
  let map=arr[Symbol.iterator]();
  console.log(map.next());
  console.log(map.next());
  console.log(map.next());
}
自定义Lterator
{
  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);
  }
}
for of 遍历(数组的时候讲过哦)
{
  let arr=['hello','world'];
  for(let value of arr){
    console.log('value',value);
  }
}

Genertor(异步编程,高级)

基本定义

返回的也是Lterator对象
yield 停车
next 开车

{
  // 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());
}
Genertor和Lterator的关系(Genertor新应用)

Genertor是一个遍历器生成函数

{
  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());
}
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 draw = function(count){
    // 具体抽奖逻辑
    console.info(`剩余${count}次`)
  }

  let residue = function* (count){
      while(count>0){
        count --;
        yield draw(count);
      }
    }
      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)


}

长轮询

一个数据状态定期变化,我们需要定时去取状态(长轮询,web Socket)
长轮询:客户端不停的向服务器发送请求以获取最新的数据信息。这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已。

// 长轮询
{
  // 轮询接口
  let ajax = function*(){
    yield new Promise(function(resolve,reject){
      // 模拟请求的耗时
      setTimeout(function(){
        resolve({code:10})
      },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.info(d);
      }
    })
  }

  pull();
}

Decorators(修饰器)

  • 是一个函数,可以用来修改类的行为
  • 需要插件babel-plugin-transform-decorators-legacy
  • 第三方库修饰器的js库:core-decorators
    只读修饰器的添加
{
  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);
        // 埋点函数 new 后执行 
        console.log('log ${type}');
      }
    }
  }

  class AD{
    @log('show')
    show(){
      console.info('ad is show')
    }

    @log('click')
    click(){
      console.log('ad is click');
    }

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

  }

}

模块化

export 导出
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 导入

入口文件


import {a,test,Hello} from './模块文件名'
升级
import * as mon from './模块文件名'

部分内容摘自阮一峰老师的博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值