代理窗口对象以检测更改

时间:2019-03-27 02:11:05

标签: javascript ecmascript-6 proxy window

我可以代理window对象来检测更改吗?我没有运气就尝试了以下方法:

var handler = {
  get: function(target, property) {
    console.log("getting " + property + " for " + target);
    return target[property];
  },
  set: function(target, property, value, receiver) {
    console.log("setting " + property + " for " + target + " with value " + value);
    target[property] = value;
    return true;
  },
};
var p = new Proxy(window, handler);
setTimeout(() => {
  window.a = 10; // expecting a log, but nothing...
}, 3000);
setTimeout(() => {
  window.c = 20; // expecting a log, but nothing...
}, 4000);

1 个答案:

答案 0 :(得分:2)

您必须在下面的代码中引用Proxy实例,而不是window

var handler = {
  get: function(target, property) {
    console.log("getting " + property + " for " + target);
    return target[property];
  },
  set: function(target, property, value, receiver) {
    console.log("setting " + property + " for " + target + " with value " + value);
    target[property] = value;
    return true;
  },
};
var p = new Proxy(window, handler);

setTimeout(() => {
  p.a = 10;    // <------------
}, 300);
setTimeout(() => {
  p.c = 20;    // <------------
}, 400);

如果您无法更改引用window的代码,则也可以将代理命名为window(并在另一个变量中保存对真实窗口的引用),但是该代码会令人困惑。

如果它在独立的脚本文件中,则上述技巧将无效,并且您将无法使用Proxy-毕竟,您无法重新定义window对象。如果您正在寻找window上特定属性的更改,则可以使用defineProperty并使设置方法在将属性描述符分配给以下属性时用新值覆盖该属性描述符:

Object.defineProperty(window, 'a', {
  configurable: true,
  set(value) {
    console.log("setting with value " + value);
    Object.defineProperty(window, 'a', { value });
  }
});

setTimeout(() => {
  window.a = 10;
  console.log(window.a);
}, 300);