2016-03-28 6 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/)を使用してください。 –

答えて

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

Danさん、私は最初の例を実行しようとしていますが、それはinfinteループを実行しています。私はこの例をchrome 48.x – Shad

+0

で実行しています。アンダースコアが見つかりませんでした。 –

+0

@Danはいチャドはあなたの最初のsolnが無限ループを実行していると言いました。 – Nirus

10

@Dan solution正しいです。

かなり古いブラウザをサポートしたい場合は、polyfillに行くことをお勧めします。

または使用免責

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

IE 9でサポートされてObject.defineProperties API:私はobject-observerライブラリの作者は、以下の提案です。

私はgetters/settersの解決策にはいきません。複雑で、スケーラブルではなく、保守不能です。バックボーンはそのように双方向バインディングを行い、正しく動作させるための定型文はかなりのコードでした。

プロキシは、必要なものを達成するための最良の方法です。上の例にいくつかのコールバック登録と管理を追加し、変更時にそれらを実行するだけです。

polyfillライブラリに関して:これらのうちのいくつかは、「ダーティチェック」またはポーリング技術を使用して実装されています。効率的ではなく、パフォーマンスがありません。場合によっては、上記のNirusによって指摘されたpolyfillのケースです。

私は、プロキシを介して観測を行うライブラリを選択することをお勧めします。そこにはいくつかありますが、object-observerのうちの1つがあります。このユースケースのために正確に書かれた、ネイティブのプロキシを利用し、ディープツリーの観察などを提供します。

+0

ブラウザサポートはどうですか? [**プロキシはpolyfilledまたはtranspiledすることはできません**](https://stackoverflow.com/questions/35025204/javascript-proxy-support-in-babel)、プロキシを使用するIMOは実際には良いアイデアではありませんプロダクション環境はまだまだです! –

+0

この実装は、Proxyオブジェクトをサポートしていない環境では実行されません。しかし、すべてのダウンロード可能な主要なブラウザは既にそこにあります(Chrome、Firefox、Opera)、実際にはEdgeです。モバイル版もあります。だから私が見ることができる唯一の懸念は、IEのプリエッジです - 個人的には私はそれを残しました。 – GullerYA

+0

企業の世界では、しばしばIEのサポートを中止することは選択肢ではありません。 –

関連する問題