2

Can I proxy the window object to detect changes? I tried the following without any luck:

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);
eozzy
  • 66,048
  • 104
  • 272
  • 428

1 Answers1

4

You have to reference the Proxy instance in your lower code, not the 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);

If you can't change the code that references the window, you could also name the proxy window (and save a reference to the true window in another variable), but the code for that would look confusing.

If it's in a standalone script file, the above trick won't work, and you won't be able to use a Proxy - you can't redefine the window object, after all. If you're looking for a change for a specific property on window, you could use defineProperty and have the setter overwrite the property descriptor with the new value when it gets assigned to:

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);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • But I only need to detect changes on `window`. The use case is to check if `window.pluginX` then initialise the plugin. Because the plugin, when loaded, adds a prop `pluginX` to `window` so I just need to check that and do my thing. – eozzy Mar 27 '19 at 02:15
  • 1
    @eozzy were you able to resolve this? I also want to listen to changes in a window property and based on that make changes to global variable which is pointing to that window property. – Zameer Haque May 05 '21 at 09:54
  • @ZameerHaque Make the window property you want to listen to into a getter/setter. – CertainPerformance May 05 '21 at 12:51
  • Yes, ended up doing that. Proxying would have been great, as the shared module which accesses the window property would not have to change the signature for calling the property. – Zameer Haque May 05 '21 at 18:58