2011-03-09 9 views
4

私は、観察者が対象で発生したイベントの特定のセットを気にオブザーバーパターンを次のオブジェクトの関係を記述しようとしています。Observer Patternの質問 - JavaScript配列自体が親配列から削除されていますか?

は、私は、これは100%の標準であるかどうかわからないんだけど、私はそれを構築してきた方法は、これらのイベントオブジェクトは、イベントが発生したときに発生しますカスタムコールバックで、観測者内で定義されています。被験者にイベントが発生すると、それはオブザーバーのすべてを通過し、このイベントを誰が見ているかを調べます。オブザーバーがこのイベントを監視している場合、オブザーバーイベントのコールバックをトリガーします。

私のオブザーバーは、監視するイベントを追加したり削除したりするのに柔軟性を持たせたいので、コールバックを実行した後でイベントオブジェクトを削除する必要があります。たとえば、私のオブザーバーがイベントに一度だけ応答したい場合は、それを監視しません。

これは良い計画のように思えるが、私は自分自身に()JavaScriptオブジェクトは、呼び出しは削除することはできませんことを知っています。

私はそこに誰がこのに走っていたされており、効果的な解決策を考え出すていただけに興味がありました。

親オブザーバオブジェクトへの参照を子イベントに渡すことができ、コールバックが発生したときに、親内のメソッドを呼び出すことができました。removeEvent(this)この関数。 removeEvent関数は、イベントの配列からイベントをスプライスすることができます。唯一の複雑な問題は、配列内のこのイベントオブジェクトの場所を見つけることだけです。 (これについての提案もありがとう!)。

ありがとうございました!

答えて

2

あなたの質問に答えてもらえたらと思っていましたが、私はあなたのオブザーバーパターンをどのように実装したのか100%確信していません。おそらく、以下の私のスニペットに役立つものがあります。私は観測がコールバック関数を介して行われていると仮定し、私は文字列を使用しているので、そのデータの形式については何も仮定していません。
私の解決策の要点は、コールバックが(オブザーバーパターンでは通常の)Subjectへの参照を受け取ることです。この参照を使用して、Subjectからコールバックを切り離すことができます。あなたの応答ジョナサンため

var Subject = { 
    observers: {}, 

    attach: function(eventType, fn) { 
     if(!this.observers[eventType]) this.observers[eventType] = []; 
     this.observers[eventType].push(fn); 
    }, 

    detach: function(fn) { 
     var newObservers, 
      eventType, 
      i; 
     for(eventType in this.observers) { 
      newObservers = []; 
      for(i = 0; i < this.observers[eventType].length; i++) { 
       if(this.observers[eventType][i] !== fn) newObservers.push(this.observers[eventType][i]); 
      } 
      this.observers[eventType] = newObservers; 
     } 
    }, 

    notify: function(eventType, data) { 
     var i, observers = this.observers[eventType].slice(0); 
     for(i = 0; i < observers.length; i++) { 
      observers[i](data, this); 
     } 
    }, 

    poke: function() { 
     this.notify('testing', 'I got poked'); 
    } 

}; 

var Observer = { 

    logEvent: function(data, subject) { 
     console.log('Every time: ' + data); 
    }, 

    logEventOnce: function(data, subject) { 
     console.log('Just once: ' + data); 
     /* 
     * THE CRUX 
     */ 
     subject.detach(arguments.callee); 
    } 
}; 

Subject.attach('testing', Observer.logEvent); 
Subject.attach('testing', Observer.logEventOnce); 

Subject.poke(); 
//Every time: I got poked 
//Just once: I got poked 

Subject.poke(); 
//Every time: I got poked 

Subject.poke(); 
//Every time: I got poked 

Subject.poke(); 
//Every time: I got poked 
+0

私はこれが好きですが、サブジェクトの "notify"ループ内から "detach"を呼び出すリスナーに対して守りたいかもしれません。 for/loop中に変更されている「オブザーバー」の長さは問題です。これを解決する方法はたくさんあります。 – selbie

+0

はい、デモです。プロダクションのためにいくつかの強化をしたいと思っています。良い点tho :) – meouw

+0

セルビーのコメントごとに通知ループの問題を修正しました。私たちはループしている配列をループ中に変更したくない – meouw

4

removeEventメソッドでイベントオブジェクトへの参照を渡すと、すべてのイベントをループして==演算子でテストできます。渡されたイベントオブジェクトは参照であるため、ループ内の対応するイベントオブジェクトと比較すると、メモリ内の同じオブジェクトを参照するため、trueに評価されます。

+0

感謝。これは私が目指している場所なので、複雑さを積み重ねるために、Ok。イベントobjがオブジェクトと関数の両方のメンバと複雑であれば、 "=="で十分でしょうか?たとえば、 'event1 = {var type =" click "; var callback = function(){alert( 'Im event1!')}; }; '' event2 = {var type = "click"; var callback = function(){alert( 'Im event2!')}; }; 'Will ==違いを伝えることができますか? – clockworked247

+1

この例では、同じ種類の同じプロパティを持っていても、event1とevent2は等しくない(==)。これは、メモリ内の2つの異なる場所を参照するためです。あなたはイベント2 = EVENT1をした場合、JavaScriptはちょうどイベント2はメモリ内の同じオブジェクトへの参照を保持し、それはEVENT1のコピーを作成しませんになり、したがって、それらは等しくなる(==) –

+0

私は毎日の新しい何かを=学びます)ありがとうJohnathan。 – clockworked247

関連する問題