20200703

@xiaojingzhao

Plan

  • 你不知道的 js 下卷 第 7 章 元编程

Notes

7.4 代理 Proxy

代理的局限性

代理有很多 traps,但是有些操作无法被拦截

var obj = {};
var handlers = {...}
pobj = new Proxy(obj, handlers)

typeof obj;
String obj;
obj + " ";
obj === pobj;
obj == pobj;

可取消的代理

let { proxy: pobj, revoke: prevoke } = Proxy.revocalble(obj, handlers);

// prevoke 是一个函数,执行后,traps会被取消
//  一旦取消,触发任意trap都会报错 --TypeError

代理在先,代理在后

前面的例子都是 代理在先 的模式,因为所有的 obj 都被代理包裹了一层,要访问 obj,需要先访问代理。

下面的例子是代理在后的例子

var handers = {
  get(target, key, context) {
    return () => {
      context.speak(key + "!");
    };
  },
};
catchall = new Proxy({}, handlers);

greater = {
  speak(who = "someone") {
    console.log("hello ", who);
  },
};

Object.setPrototypeOf(greeter, catchall);

greater.speak(); // hello someone
greater.spaek("world"); // hello world

greeter.everyone(); // hello everyone!

上面的例子,通过 obj 本事去访问了 proxy 的 trap,所以是代理在后。

关于代理在前和代理在后,在希望访问某个不存在的属性时提供错误信息的时候,代理在后的模式下,代码比较优雅简洁。

//  将上面的例子中的handler修改一下
var handers = {
  get() {
    // 属性不存在
  },
  set() {
    // 属性不存在
  },
};
// 这样能工作的原因是因为,只有当 obj 中的属性不存在时,才会 trap 到 handler 中的 get 和 set

代理 hack [[prototype]] 链

demo 模拟原型,原理非常简单:


More