Доступ к методам get / set для свойства JavaScript, созданного с помощью Object.create - PullRequest
3 голосов
/ 25 марта 2012

Что мне нужно, так это возможность обернуть свойство JavaScript для изменения поведения при получении / установке.

Для свойств, которые являются значениями, я могу сделать следующее:

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 уже имеет геттер / установщик?

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 не работает.

1 Ответ

6 голосов
/ 11 апреля 2012
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, чтобы получить полный список имен свойств для изменения.

См. MDN для объяснения Object.getOwnPropertyDescriptor .

...