Listening for variable changes in JavaScript

后端 未结 22 2814
自闭症患者
自闭症患者 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:25

    As Luke Schafer's answer (note: this refers to his original post; but the whole point here remains valid after the edit), I would also suggest a pair of Get/Set methods to access your value.

    However I would suggest some modifications (and that's why I'm posting...).

    A problem with that code is that the field a of the object myobj is directly accessible, so it's possible to access it / change its value without triggering the listeners:

    var myobj = { a : 5, get_a : function() { return this.a;}, set_a : function(val) { this.a = val; }}
    /* add listeners ... */
    myobj.a = 10; // no listeners called!
    

    Encapsulation

    So, to guarantee that the listeners are actually called, we would have to prohibit that direct access to the field a. How to do so? Use a closure!

    var myobj = (function() { // Anonymous function to create scope.
    
        var a = 5;            // 'a' is local to this function
                              // and cannot be directly accessed from outside
                              // this anonymous function's scope
    
        return {
            get_a : function() { return a; },   // These functions are closures:
            set_a : function(val) { a = val; }  // they keep reference to
                                                // something ('a') that was on scope
                                                // where they were defined
        };
    })();
    

    Now you can use the same method to create and add the listeners as Luke proposed, but you can rest assured that there's no possible way to read from or write to a going unnoticed!

    Adding encapsulated fields programmatically

    Still on Luke's track, I propose now a simple way to add encapsulated fields and the respective getters/setters to objects by the means of a simple function call.

    Note that this will only work properly with value types. For this to work with reference types, some kind of deep copy would have to be implemented (see this one, for instance).

    function addProperty(obj, name, initial) {
        var field = initial;
        obj["get_" + name] = function() { return field; }
        obj["set_" + name] = function(val) { field = val; }
    }
    

    This works the same as before: we create a local variable on a function, and then we create a closure.

    How to use it? Simple:

    var myobj = {};
    addProperty(myobj, "total", 0);
    window.alert(myobj.get_total() == 0);
    myobj.set_total(10);
    window.alert(myobj.get_total() == 10);
    

提交回复
热议问题