【问题标题】:How to observe value changes in JS variables如何观察JS变量的值变化
【发布时间】:2011-02-10 12:14:55
【问题描述】:

我想知道是否有人可以帮助我做一些我认为相当直接的事情:

基本上我想扩展所有数据类型(包括内在类型)的原型,以允许某种自定义函数,请考虑:

var x = "some string";
var y = 101;

x = "some other value";
y++;

x.onChange();
y.onChange();

这是我之后的基本想法,但我真正想要的是实际上让 onChange(在本例中)有所不同,因此实际变量的新函数(而不是标准原型扩展),即:

x.onChange = function() {
    alert("x.onChange");
}

y.onChange = function() {
    alert("y.onChange");
}

这似乎不起作用,但我一定错过了一些非常简单的东西,不是吗?我的意思是我当然可以扩展所有对象和类型并添加新功能......不是吗?

任何帮助将不胜感激!

【问题讨论】:

    标签: javascript observable watch


    【解决方案1】:

    我可能不想通过尝试向现有类型添加方法来解决此问题,而是创建一个可以包装原始类型的对象。我将其称为“观察”一个值,并且可能会像这样实现它:

    function observable(v){
        this.value = v;
    
        this.valueChangedCallback = null;
    
        this.setValue = function(v){
            if(this.value != v){
                this.value = v;
                this.raiseChangedEvent(v);
            }
        };
    
        this.getValue = function(){
            return this.value;
        };
    
        this.onChange = function(callback){
            this.valueChangedCallback = callback;
        };
    
        this.raiseChangedEvent = function(v){
            if(this.valueChangedCallback){
                 this.valueChangedCallback(v);
            }   
        };
    }
    

    这可用于观察任何值的变化(只要该值仅由可观察类上的方法更改 - 一个小小的减损 IMO)。

    上面的代码可以使用这样的东西:

    var obs = new observable(123);
    obs.onChange(function(v){
             alert("value changed to: " + v);
         });
    
    // the onChange callback would be called after something like obs.setValue(456);
    

    这里的例子 --> http://jsfiddle.net/MeAhz/

    【讨论】:

    • 非常感谢 Jamie...这是我试图解决的问题的一个非常优雅的解决方案...再次感谢!
    【解决方案2】:

    扩展对象原型:

    Object.prototype.foo = function() { alert('hello world'); };
    var a = 1;
    a.foo();
    

    【讨论】:

    • @insin:FWIW,ECMA-262 第 5 版的 defineProperty() 可以通过定义不可枚举的属性来解决该特定问题。所以可以使用Object.prototype.hasOwnProperty()
    • 另外,这个问题是你只有一个函数,而不是一个处理程序,即:'var a = 1;变量 b = 2; a.foo(); b.foo();'在那个例子中'a.foo();'和'b.foo();'做同样的事情
    • Tat 正是我想要的,当我向Object prototype 添加一个函数时...单个函数中的每个对象...我可以将一个名为 _name 的函数添加到原型并在函数中切换要返回的属性,在视图中我所要做的就是{{ item._name }}
    【解决方案3】:

    标准的弃用方式:Object.observe()

    Object.observe() 方法用于异步观察 改变一个对象。它提供了顺序的变化流 它们发生。但是,此 API 已被弃用并删除 从浏览器。

    let myObservdObject = Object.observe( { a : 'foo' }, e=>console.log('change!', e) );
    myObservdObject.a = 'bee';
    // callback gets executed
    // and prints 'changed! in console, with the change event data
    

    但是代理到达标准 (ES6) 时,Object.Observe 已被弃用,因此浏览器不支持。

    代理是观察的新方式...但与 Object.observe 过去提供给我们的方式相比,实现通用观察器需要更复杂的实现。


    通过第三方库观察值变化

    您可以找到许多基于代理的实现。 其中一些实现了观察者模式,这迫使您使用特定方法设置或获取值:

    观察https://www.npmjs.com/package/observe

    // define your object
    var object = {a:'bee'};
    // generate an observer
    var observer = observe(object);
    // declare the onchange event handler
    observer.on( 'change', change=> console.log(change) );
    // ready!
    // set the value of 'a' and see how the callback is executed...
    observer.set('a', 'foo')   
    // get the new value
    observer.get('a')   // returns 'foo'
    

    取而代之的是其他库,让您以更自然的方式与变量进行交互:

    WatchJShttps://github.com/melanke/Watch.JS/

    // define your object
    var object = {a:'bee'};
    // generate an observer and declare de hadler
    watch(object , "a" , e=>console.log(e) );
    // ready!
    // set the value of 'a' and see how the callback is executed...
    object.a = 'foo';   
    // get the new value
    object.a  // returns 'foo'
    

    我自己的方法:深度观察者

    所有实现都有自己的注意事项,没有一个适合我的目的,所以我必须实现自己的方法。

    结果是一个高度可定制的 Observer 方法,占用空间非常小(

    深度观察者https://www.npmjs.com/package/deep-observer

    // create an observable object
    const myObserved = new Observer( { a : 'bee' } , e=>console.log(e) ),
    // perform a modification
    myObserved.a = 'foo'; 
    // console  : { action:'update', oldValue:'bee', object:{a:'foo'}, name:'a' }
    myObserved.a;  // returns 'foo'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2021-01-26
      • 2018-11-18
      • 1970-01-01
      • 2016-12-21
      • 2022-12-15
      • 1970-01-01
      相关资源
      最近更新 更多