1

私は、現在作業中のプロジェクトに対して非常に単純なObserverクラスを構築中です。私はsubscribe、unsubscribe、notifyメソッドを実装しました。 「通常」の関数(var f = function())を使用すると、すべてが期待どおりに機能します。Javascriptでの匿名関数参照

しかし、匿名関数をsubscribeメソッドに渡して、「同じ」匿名関数を受け入れようとすると、(期待通りに)配列から関数が削除されません。 。

は、ここに私が購読して配信停止方法

this._subscribers = {}; 
subscribe: function(type, callback) { 
    if (isUndefined(this._subscribers[type])) { 
     this._subscribers[type] = []; 
    } 
    this._subscribers[type].push(callback); 
}, 
unsubscribe: function(type, callback) { 
    if (this._subscribers[type] instanceof Array) { 
     var index = this._subscribers[type].indexOf(callback); 
     if (index >= 0) { 
      this._subscribers[type].splice(index, 1); 
     } 
    } 
}, 

だと、ここで私がテストしていたコードです:私は、オブジェクトを使用して可能性が知っている

var o = new gaf.events.Observable(); 
o.subscribe('testEvent', function(event) { alert('Got It!'); }); 
o.notify('testEvent'); 
// Correct alerts 'Got It!' 
o.unsubscribe('testEvent', function(event) { alert('Got It!'); }); 
o.notify('testEvent') 
// Incorrectly alerts 'Got It!' 

(すなわち:_subscribers [イベント] = { })そして何かが購読するとき、私はコールバックと等しい値とコールバックと等しい新しいプロパティを追加することができました。これは、JavaScriptが文字列にコールバックを変換する原因になります。その文字列を使って、それを調べることができます(サブ/ unsubで渡されたメソッドがまったく同じである場合)。

しかし、これはモバイルプロジェクトであり、多くの加入者になる可能性があるため、プロパティとして長さが数百文字の文字列を格納することについては非常に心配しています。

これを行う方法は他にありますか?関数の文字列値をハッシュしてそのプロパティとして使用することができるSMALL(小、偶数)ハッシュライブラリがありますか?配列(実際のコールバックではなく)のコールバックの文字列値を格納する方が良いでしょうか?

事前に感謝します!すべての返信用

EDIT

まず、感謝! 「なぜさえ合格匿名」機能に関するすべての質問パー

- 本当に1という名前の関数を使用することができなかった理由はない

。実際、名前付き関数がより良い解決策になると誰もが同意します。私は単に情報を収集して解決策を探していますので、できるだけ多くのシナリオを処理する実装を構築することができます。

もう1つの理由は、このObservableクラスのユーザー(同僚)が匿名関数を渡してからサブスクライブを解除した場合です。その関数は実際には登録解除されないので、クリーンアップされません。私は孤立したデータに対して何かを持っています:)

コールバックが匿名であるかどうかをテストすることは可能でしょうか?私は否定するつもりだけど、頼むように傷つけない。

+1

'eval'は悪です。 – SLaks

+1

モバイルプロジェクトであるため、匿名機能(サブスクライブ用とサブスクライブ用)を複製してスペースを無駄にしたくないと思います。また、ハッシュライブラリのオーバーヘッド(スペースとパフォーマンスの両方)が必要です。ハッシュライブラリは、関数を "文字列化"し、それをハッシュする必要があります。 "stringify"操作は、適切に空白を持つ必要があります。このすべては頭痛のように聞こえる。変数に関数を保存するか、名前付き関数を使うというベストプラクティスに従うことをお勧めします。 –

+0

コメントありがとう!これが、私が先に進んでハッシュ関数を実装したのではない理由です。モバイルデバイス上のそのプロセスのオーバーヘッドと複雑さが私を驚かせました。 –

答えて

0

おそらく、より良い解決策は

var f = function() { alert('Got It!'); }; 
o.subscribe('testEvent', f); 
o.notify('testEvent'); 
o.unsubscribe('testEvent', f); 
o.notify('testEvent'); 

あなたのライブラリーを使用してコードを修正することであるあなたも、その後、購読方法

var f = o.subscribe('testEvent', function() { alert('Got It!'); }); 
// ... 

から機能を返すことができますサブスクライブされた関数の他の識別子は、呼び出しコードに対して不透明であるため、戻り値を使用してサブスクライブ解除するだけで、ライブラリは実装の詳細を隠します。

2

文字列全体の保存に問題はありません。早すぎる最適化は悪いことです。

しかし、これは信じられないほど悪い考えです。
誰かが機能を変更したが、サブスクライブされていないコピーを忘れた場合、コードは微妙に壊れてしまい、警告は何も表示されません。

代わりに、匿名関数を登録解除する必要がある場合は、変数に匿名関数を格納するようユーザーに要求することができます。
また、各サブスクライバにオプションの名前を渡してから、その名前でサブスクライブすることもできます。

+0

洞察に感謝します!私はそれが完全に悪い考えを文字列を格納することに同意します。私はちょうど私が問題について持っていたいくつかの考えを捨てていた:) –

1

オブザーバーを使用するクライアントは、関数への参照を格納する必要があります。無名関数ではなく、名前のものを渡す、またはそれ以降の退会のために使用することができます参照を維持する理由は何ですか

つまり
var obsCallback = function() { 

    } 
    o.subscribe('test', obsCallback); 
    .... 
    o.unsubscribe('test', obsCallback); 

、周りの関数への参照を保持...

0

また、オプションの「id」引数を使用できますが、重複を避けるために不必要に複雑な簿記が必要になります。あなたはハッシュまたは一部を保存したい場合は