拦截 javascript 值设置器

dan*_*ial 1 javascript setter prototype listener interceptor

如何在不丢失其他侦听器的情况下侦听变量或对象属性上设置的值。

例如

var myModel;
myModel = 10;
var myListener1 = function(oldVal, newVal) {
    //do stuff
}
var myListener2 = function(oldVal, newVal) {
    //do other stuff
}
Run Code Online (Sandbox Code Playgroud)

在这里,我希望每当为变量 myModel 设置值时调用 myListener1 和 myListener2。稍后在其他函数中可能还想在 setter 上向 myModel 添加另一个侦听器,因此它不应该覆盖现有侦听器。

我知道应该有一种方法可以使用 Object.defineProperty() 来做到这一点。另外,如果有一个针对 IE8+ 的跨浏览器解决方案就好了。

Joe*_*ons 5

对于以下方法,您必须使用带有属性的对象,但它可以工作。


// this is very similar to using Object.watch()
// instead we attach multiple listeners
var myModel = (function () {
    var actualValue,
        interceptors = [];

    function callInterceptors(newValue) {
        for (var i = 0; i < interceptors.length; i += 1) {
            interceptors[i](newValue);
        }
    }

    return {
        get value() {
            // user never has access to the private variable "actualValue"
            // we can control what they get back from saying "myModel.value"
            return actualValue;
        },

        set value(newValue) {
            callInterceptors(newValue);
            actualValue = newValue;
        },

        listen : function (fn) {
            if (typeof fn === 'function') {
                interceptors.push(fn);
            }
        }
    };
}());

// add a listener
myModel.listen(function (passedValue) {
    alert('You tried to set myValue to ' + passedValue);
});

// add another listener
myModel.listen(function (passedValue) {
    alert('AAARRG! Why did you modify that value to ' + passedValue + '?!?!');
});

// our functions are called when we
// modify our value
myModel.value = 10;
Run Code Online (Sandbox Code Playgroud)


jsFiddle 示例