简体   繁体   中英

How to Monitor the Setting of new Properties on Javascript Objects

How could I get a callback whenever new properties are set on a Javascript Object..?
Ie I don't know which properties are going to be set, but want a callback for any properties that are set.

What I want is

var obj = {};
obj.a = "something"; // triggers callback function

function callback(obj,key,val) {
    console.log(key + " was set to " + val + " on ", obj);
}

Is this possible?

You can use the new defineProperty :

function onChange(propertyName, newValue){
...
}

var o = {};

Object.defineProperty(o, "propertyName", { 
 get: function() {return pValue; },
 set: function(newValue) { onChange("propertyName",newValue); pValue = newValue;}});

But depends on the browser version you need to support.

Edit: Added snippet on Jsfiddle, works in IE10. http://jsfiddle.net/r2wbR/

Unfortunately, JavaScript won't let you know when a property is changed. Many times I've wished it would, but since it wouldn't I've had to find a workaround. Instead of setting the property directly, set it via a setter method which triggers the callback function (and possible use a getter method to access the property too) like this:

function callback(obj,key,val) {
    console.log(key + " was set to " + val + " on ", obj);
}

var obj = {};
obj.setA=function(value){
    obj.a=value;
    callback(obj,'a',value);// triggers callback function
}
obj.getA=function(){
    return obj.a;
}

obj.setA("something");

jsFiddle: http://jsfiddle.net/jdwire/v8sJt/

EDIT: Another option if you want to completely prevent changing the property without a callback:

function callback(obj,key,val) {
    console.log(key + " was set to " + val + " on ", obj);
}

var obj={};
(function(){
   var a=null;
   obj.setA=function(value){
       a=value;
       callback(obj,'a',value);// triggers callback function
   }
   obj.getA=function(){
       return a;
   }
})()

console.log("a is "+obj.getA());// a is null
obj.setA("something"); // Set a to something
console.log("a is now "+obj.getA()); // a is now something
obj.a="something else"; // Set obj.a to something else to show how a is only accessible through setA
console.log("a is still "+obj.getA()); // a is still something

jsFiddle: http://jsfiddle.net/jdwire/wwaL2/

The best thing to do it is a setter function, you don't need a getter,

var obj = {};
setKey(obj, 'a', "something"); // triggers callback function

function setKey(obj, key, val){
    obj[key] = val;
    callback(obj, key, val);
}

function callback(obj, key, val) {
    console.log(key + " was set to " + val + " on ", obj);
}

Do it as generic as you can, don't do a different function for all keys

Try it here

The best idea is to have setter and getter methods. But according to your previous implementation one could still alter your object properties without using setter and getter. Therfore you should make you senstive variables privat. Here is a brief example:

var Person = (function() {

    function Person() {};

    var _name;

    Person.prototype.setName = function(name) {

        _name = name;

    };

    Person.prototype.getName = function() {

        return _name;

    };

    return Person;

})();

var john = new Person();

john.getName();

// => undefined

john.setName("John");
john.getName();

// => "John"

john._name;

// => undefined

john._name = "NOT John";
john.getName();

// => "John"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM