Listening for variable changes in JavaScript

后端 未结 22 2831
自闭症患者
自闭症患者 2020-11-21 06:57

Is it possible to have an event in JS that fires when the value of a certain variable changes? JQuery is accepted.

22条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-21 07:13

    Most of the answers to this question are either outdated, ineffective, or require the inclusion of large bloated libraries:

    • Object.watch and Object.observe are both deprecated and should not be used.
    • onPropertyChange is a DOM element event handler that only works in some versions of IE.
    • Object.defineProperty allows you to make an object property immutable, which would allow you to detect attempted changes, but it would also block any changes.
    • Defining setters and getters works, but it requires a lot of setup code and it does not work well when you need to delete or create new properties.

    Today, you can now use the Proxy object to monitor (and intercept) changes made to an object. It is purpose built for what the OP is trying to do. Here's a basic example:

    var targetObj = {};
    var targetProxy = new Proxy(targetObj, {
      set: function (target, key, value) {
          console.log(`${key} set to ${value}`);
          target[key] = value;
          return true;
      }
    });
    
    targetProxy.hello_world = "test"; // console: 'hello_world set to test'
    

    The only drawbacks of the Proxy object are:

    1. The Proxy object is not available in older browsers (such as IE11) and the polyfill cannot fully replicate Proxy functionality.
    2. Proxy objects do not always behave as expected with special objects (e.g., Date) -- the Proxy object is best paired with plain Objects or Arrays.

    If you need to observe changes made to a nested object, then you need to use a specialized library such as Observable Slim (which I have published) which works like this:

    var test = {testing:{}};
    var p = ObservableSlim.create(test, true, function(changes) {
        console.log(JSON.stringify(changes));
    });
    
    p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
    

提交回复
热议问题