2016-03-28 137 views
28

有沒有其他方法?Object.observe()爲什麼不推薦使用

有沒有另一種方法可以在對象中進行變更檢測?

有代理的方法,但任何人都可以告訴我怎麼才能做到這一點使用代理服務器:

var obj = { 
    foo: 0, 
    bar: 1 
}; 

Object.observe(obj, function(changes) { 
    console.log(changes); 
}); 

obj.baz = 2; 
// [{name: 'baz', object: <obj>, type: 'add'}] 

obj.foo = 'hello'; 
// [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}] 
+2

'Proxy()'現在有! – Jai

+1

[Proxy](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy) –

+1

或者使用[getter](https://developer.mozilla.org/en/docs/ Web/JavaScript/Reference/Functions/get)或[setter](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/set) –

回答

34

你可以用getter和setter方法實現這一目標。

var obj = { 
    get foo() { 
    console.log({ name: 'foo', object: obj, type: 'get' }); 
    return obj._foo; 
    }, 
    set bar(val) { 
    console.log({ name: 'bar', object: obj, type: 'set', oldValue: obj._bar }); 
    return obj._bar = val; 
    } 
}; 

obj.bar = 2; 
// {name: 'baz', object: <obj>, type: 'set', oldValue: undefined} 

obj.foo; 
// {name: 'foo', object: <obj>, type: 'get'} 

或者,在支持代理的瀏覽器中,您可以編寫更通用的解決方案。

var obj = { 
    foo: 1, 
    bar: 2 
}; 

var proxied = new Proxy(obj, { 
    get: function(target, prop) { 
    console.log({ type: 'get', target, prop }); 
    return Reflect.get(target, prop); 
    }, 
    set: function(target, prop, value) { 
    console.log({ type: 'set', target, prop, value }); 
    return Reflect.set(target, prop, value); 
    } 
}); 

proxied.bar = 2; 
// {type: 'set', target: <obj>, prop: 'bar', value: 2} 

proxied.foo; 
// {type: 'get', target: <obj>, prop: 'bar'} 
+1

感謝丹,我試圖運行它正在運行infinte循環的第一個示例。我在鉻48.x – Shad

+0

哎呀運行此示例。錯過了下劃線。 –

+0

@丹是的乍得提到你的第一個soln運行無限循環。 – Nirus

10

@Dan solution是正確的

如果你想支持比較老的瀏覽器,我建議你去polyfill

或使用Object.defineProperties API它支持在IE 9

var obj = Object.defineProperties({}, { 
    "foo":{ 
     get:function(){ 
      console.log("Get:"+this.value); 
     }, 
     set:function(val){ 
      console.log("Set:"+val); 
      this.value = val; 
     } 
    }, 

    "bar":{   
     get:function(){ 
      console.log("Get:"+this.value); 
     }, 
     set:function(val){ 
      console.log("Set:"+val); 
      this.value = val; 
     } 
    } 
}); 
5

免責聲明:我是object-observer庫筆者建議如下。

我不想和getters/setters解決方案一起使用 - 它很複雜,不可擴展且不可維護。 Backbone以這種方式進行了雙向綁定,並且使其正確工作的樣板文件是相當一部分代碼。

代理是實現所需內容的最佳方式,只需在上面的示例中添加一些回調註冊和管理,並在發生更改時執行它們。

至於polyfill圖書館:一些/大多數這些實施利用「髒檢查」或輪詢技術 - 效率不高,不表現。有時候,這是Nirus上面指出的polyfill的情況。

我建議選擇一些通過代理進行觀察的庫。有幾個,object-observer就是其中之一:正是爲這個用例編寫的,利用了本地代理,提供了深層樹的觀察等。

+0

瀏覽器支持如何? [**代理不能被polyfilled或transpiled **](https://stackoverflow.com/questions/35025204/javascript-proxy-support-in-babel),所以IMO使用代理不是一個好主意生產環境尚未完成! –

+0

沒錯,這個實現不會在任何不支持代理對象的環境中運行。然而,所有可下載的主要瀏覽器已經在那裏(Chrome,Firefox,Opera)以及Edge。移動版本也在那裏。所以我唯一能夠看到的是IE前的Edge--我親自把它留在了後面。 – GullerYA

+0

在企業界,通常不會放棄IE支持。 –

相關問題