ES6中的 Proxy 和 Reflect

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m_review/article/details/90443242

Proxy

含义

在目标对象之前架设一层 拦截 ,访问该对象时必须经过这层拦截,对外界的访问进行过滤和改写

let obj = new Proxy(
  {},
  {
    get: function(target, key, receiver) {
      console.log(`get ${key}`);
      return Reflect.get(target, key, receiver);
    },
    set: function(target, key, value, receiver) {
      console.log(`set ${key}`);
      return Reflect.set(target, key, value, receiver);
    }
  }
);

obj.count = 1; // set count
++obj.count; // get count  set count

api

var proxy = new Proxy(target, handler);

target : 所要拦截的目标对象

handler : 定制拦截操作

支持 13 个拦截操作

set、get、has、deleteProperty、apply、construct …

具体参考:http://es6.ruanyifeng.com/#docs/proxy#Proxy-实例的方法

Proxy.revocable()

Proxy.revocable() 返回一个可取消的 Proxy 实例

// revoke: 取消 Proxy 实例
let { proxy, revoke } = Proxy.revocable({}, {});

proxy.foo = 123;
proxy.foo; // 123
revoke();
proxy.foo; // TypeError: Revoked

当执行 revoke 函数之后,再访问 Proxy 实例,就会抛出一个错误。

this 问题

在 Proxy 代理的情况下,目标对象内部的 this 关键字会指向 Proxy 代理。

let target = {
  m: function() {
    console.log(this === proxy);
  }
};
let handler = {};
let proxy = new Proxy(target, handler);

target.m(); // false
proxy.m(); // true

web 服务的客户端

Proxy 对象可以拦截目标对象的任意属性,这使得它很合适用来写 Web 服务的客户端:

const service = createWebService("http://example.com/data");

service.employees().then(json => {
  const employees = JSON.parse(json);
  // ···
});

尝尽:Proxy 可以拦截 service 对象的任意属性,所以不用为每一种数据写一个适配方法,只要写一个 Proxy 拦截就可以了。

function createWebService(baseUrl) {
  return new Proxy(
    {},
    {
      get(target, propKey, receiver) {
        return () => httpGet(baseUrl + "/" + propKey);
      }
    }
  );
}

使用 Proxy 实现观察者模式

观察者模式 :函数自动观察数据对象,一旦数据发生变化,函数就会自动执行

// person 观察目标
const person = observable({
  name: "kk",
  age: 12
});

// print 观察者
function print() {
  console.log(`打印:姓名 ${person.name}, 年龄 ${person.age}`);
}

observe(print);

person.name = "lisi";

使用 Proxy 写一个观察者模式的最简单实现,即实现 observableobserve 这两个函数。

思路:observable 函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数

const queuedObservers = new Set();

const observe = fn => queuedObservers.add(fn);

const observable = obj =>
  new Proxy(obj, {
    set
  });

function set(target, key, value, receiver) {
  // 拦截赋值操作
  const result = Reflect.set(target, key, value, receiver);
  // 触发各个观察者
  queuedObservers.forEach(observer => observer());
  return result;
}

Reflect

作用

  • 从 Reflect 对象上拿语言内部的方法

  • 修改某些 Object 方法的返回结果

    比如:在无法定义属性时,Object 会抛出一个错误,Reflect 会返回 false

  • 让 Object 命令式操作都变成函数行为

    // 老写法
    "assign" in Object; // true
    // 新写法
    Reflect.has(Object, "assign"); // true
    
  • Reflect 对象的方法与 Proxy 对象的方法一一对应

Reflect 对象的 13 个静态方法

get、set、has、deleteProperty、apply、construct …

具体参考:http://es6.ruanyifeng.com/#docs/reflect#静态方法

猜你喜欢

转载自blog.csdn.net/m_review/article/details/90443242
今日推荐