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

本文深入讲解了JavaScript中的新特性,包括Proxy与Reflect的区别与应用场景、类与对象的使用方法、Promise处理异步操作的方式及其实用场景、Iterator与Generator的用法及其实例等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 './模块文件名'

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

“--lib”选项的参数必须为 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'es2023.intl', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'esnext.regexp', 'esnext.iterator', 'decorators', 'decorators.legacy'。
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值