每当对象属性发生更改时,Javascript都会实现回调

时间:2014-10-27 20:29:40

标签: javascript

每当对象属性发生变化时,我都需要回调一些东西,类似于Object.watch和Object.observe。但是,那些还没有跨浏览器。

我需要支持以下内容:

  1. 支持同一属性上的多个手表 同一个对象
  2. 它不能改变对象
  3. 必须有一种方法可以在不影响他人的情况下取消特定的手表。
  4. 我实施了以下符合标准1)和2)但不符合3):

    /**
     * Add getter/setter to the obj so that the callback is called whenever the property value is changed
     * Returns a function that cancels the watch
     * @param {object} obj
     * @param {string} prop
     * @param {function} callback
     * @return {function}
     */
    function watch(obj,prop,callback){
        if (obj[prop]===undefined || !obj.hasOwnProperty(prop)){
            throw new Error("Dangerous use of watch, "+obj+" does not have ["+prop+"]");
        }
        var prevState = Object.getOwnPropertyDescriptor(obj,prop);
        var _var = obj[prop];
    
        Object.defineProperty(obj,prop,{
            set: prevState.set === undefined ?
                function(value){
                    _var = value;
                    callback(value);
                }
                :
                function(value){
                    prevState.set(value);
                    callback(prevState.get());
                },
            get: prevState.get === undefined ?
                function(){
                    return _var;
                }
                :
                function(){
                    return prevState.get();
                }
        });
    
        return function cancelWatch(){
            console.log(Object.getOwnPropertyDescriptor(obj,prop));
            var val = obj[prop];
            delete obj[prop];
            if (prevState.get !== undefined || prevState.set !== undefined){
                Object.defineProperty(obj,prop,{
                    get: prevState.get,
                    set: prevState.set
                })
            } else {
                obj[prop] = val;
            }
        };
    }
    

    例如;这有效:

    var o = {};
    o.a = 1;
    
    var c0 = watch(o,"a",function(v){console.log("watch: "+v)});
    var c1 = watch(o,"a",function(v){console.log("watch: "+v)});
    
    > o.a = 5;
    "watch 5"
    "watch 5"
    

    然而,问题在于取消。如果我调用c1(),一切都很好,因为它只是弹出其getter / setter。但是,如果我调用c0,那不起作用,因为它会在调用第一个手表之前将getter / setter状态重置为第二个手表,从而消除了第二个手表的触发。我的问题是,有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:1)

不应该自己编写,而应该尝试查找并使用现有的填充程序(只需谷歌“Object.observe shim”)

尽管如此,我还是尝试修复您的代码:http://jsbin.com/jupuro/2/edit?js,console