Accessing get / set methods for a JavaScript property created using Object.create

What I would like is to be able to wrap a JavaScript property to change behavior in the get / set.

For properties that are values, I can do the following:

var obj = {
    myProperty : 0
};

function notifyOfChange(obj, propertyName) {
    var propertyValue = obj[propertyName];
    Object.defineProperty(obj, propertyName, {
        get : function() { return propertyValue; },
        set : function(newValue) {
            var propertyValue = newValue;
            console.log("Message from notifyOfChange."); 
        }
    });
};

obj.myProperty = 10; // outputs "Message from notifyOfChange."

      

However, what if myProperty already has a getter / setter?

var obj = Object.create({}, {
    myProperty : {
        get : function() { return this._myProperty; },
        set : function(value) {
            console.log("Message from obj itself.");
            this._myProperty = value;
        },
        configurable : true
    }
});

obj.myProperty = 10; // outputs "Message from obj itself";

notifyOfChange(obj, "myProperty");

obj.myProperty = 10; // outputs "Message from notifyOfChange."

      

Is there a way to detect the myProperty anonymous setter so that I can call it in notifyOfChange ?

Note. I want to make notifyOfChange work with any object, so just using a named function for the myProperty setter does n't work.

+3


source to share


1 answer


function notifyOfPropertyChange(obj, propertyName) {

    var desc = Object.getOwnPropertyDescriptor(obj, propertyName);

    if ("value" in desc && desc.writable) {
        // Value property

        var propertyValue = obj[propertyName];

        Object.defineProperty(obj, propertyName, {
            get: function () { return propertyValue; },
            set: function (newValue) {
                propertyValue = newValue;
                console.log("Message from notifyOfChange.");
            },
            configurable: true,
            enumerable: desc.enumerable
        });

    } else if (desc.set) {
        // Getter/setter property

        // Redefine the setter, keep the getter if it exists
        var originalSet = desc.set.bind(obj);
        desc.set = function (newValue) {
            originalSet(newValue);
            console.log("Message from notifyOfChange.");
        };
        Object.defineProperty(obj, propertyName, desc);
    }
}

      

You can use Object.getOwnPropertyNames

to get a complete list of property names to change.



See MDN for an explanation of Object.getOwnPropertyDescriptor .

+5


source







All Articles