ECMAScript 6 Reflect / Proxy

基础

Reflect

建议先看 Reflect 然后再看 Proxy。该对象用于拦截 JavaScript 操作的方法。

示例代码参考: https://www.javascripttutorial.net/es6/javascript-reflection/

在了解了 Reflect 和 Proxy 之后,还可以再深入了解一下 React.metadata: reflect-metadata

Proxy

代理是可以实现拦截和自定义的。

示例代码参考: https://www.javascripttutorial.net/es6/javascript-proxy/

实用指南: https://blog.bitsrc.io/a-practical-guide-to-es6-proxy-229079c3c2f0

Demo

const axios = require('axios');



const SDK = (options) => {

  const client = axios.create(options);

  return new Proxy(

    {},

    {

      get: (_, property) => client[property.toLowerCase()]

    }

  );

};



const client = SDK({

  baseURL: 'https://api.xxxx.com',

  timeout: 1000,

  headers: {

    'X-Custom-Header': 'foobar'

  }

});



// Use just like axios:

client.get('/xxx').then();



client

  .post('/xxx', {

    // form body

  })

  .then();

问题

TypeError

不规范的使用会导致报错,并且该方式的调用无法被捕获

const p = new Proxy(

  {},

  {

    get: (target, property, receiver) => {

      console.log(target, property, receiver);

      try {

        return property;

      } catch (e) {

        console.log(e.message);

        return '';

      }

    }

  }

);



console.log(p.test);

console.log(p.test());



/*

{} test {}

test

{} test {}

/Users/v0/Projects/Authing/demos/proxy-sdk/index.js:17

console.log(p.test());

              ^



TypeError: p.test is not a function

    at Object.<anonymous> (/Users/v0/Projects/Authing/demos/proxy-sdk/index.js:17:15)

    at Module._compile (node:internal/modules/cjs/loader:1101:14)

    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)

    at Module.load (node:internal/modules/cjs/loader:981:32)

    at Function.Module._load (node:internal/modules/cjs/loader:822:12)

    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)

    at node:internal/main/run_main_module:17:47

*/

如果这样写的话:

const p = new Proxy(

  {},

  {

    get: (target, property, receiver) => {

      console.log(target, property, receiver);

      return () => property;

    }

  }

);



console.log(p.test);

console.log(p.test());

/*

{} test {}

[Function (anonymous)]

{} test {}

test

*/

虽然不会报错,但是强制了返回为 Function。如果想要更灵活的运用,则不能仅使用空对象进行扩展,需要配合 set 去针对性设置某些 property

示例:

const p = new Proxy(

  {},

  {

    construct: (target) => {},

    get: (target, property, receiver) => {

      console.log(target, property, receiver);

      // 注入的方法

      if (target.hasOwnProperty(property)) {

        return target[property];

      }

      return () => property;

    }

  }

);



// 简单的方法之一: 配合 Reflect 使用

Reflect.set(p, 'test', 'test1');



console.log(p.test);

console.log(p.test2());

/*

{ test: 'test1' } test { test: 'test1' }

test1

{ test: 'test1' } test2 { test: 'test1' }

test2

*/

简单示例

可以配合使用 Reflect Metadata 来注入拦截。比如说创建 Before Hook、 After Hook 等。

// import 'reflect-metadata';

require('reflect-metadata');



const p = new Proxy(

  {},

  {

    construct: (target) => {},

    get: (target, property, receiver) => {

      const injected = Reflect.getMetadata('before', p, property);

      if (injected) injected();

      if (target.hasOwnProperty(property)) {

        return target[property];

      }

      return () => property;

    }

  }

);



Reflect.defineMetadata(

  'before',

  () => {

    console.log('BeforeEach');

  },

  p,

  'test'

);



console.log(p.test());

Refs

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Willin 老王带你躺平养老

感谢你这么好看还这么慷慨

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值