访问使用Object.create创建的JavaScript属性的get / set方法

时间:2012-03-24 20:07:33

标签: javascript object-create defineproperty

我想要的是能够包装JavaScript属性以修改get / set上的行为。

对于值的属性,我可以执行以下操作:

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."

但是,如果 myProperty 已经有一个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."

有没有办法检测 myProperty 匿名设置器,以便我可以在 notifyOfChange 中调用它?

注意:我想使notifyOfChange适用于任何对象,因此只使用 myProperty setter的命名函数不起作用。

1 个答案:

答案 0 :(得分:6)

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);
    }
}

您可以使用Object.getOwnPropertyNames获取要修改的属性名称的完整列表。

有关Object.getOwnPropertyDescriptor的解释,请参阅MDN。