関数呼び出しイベントのエミュレーション

約6か月前、彼らは私に次のような質問をしました。「ユーザーのアクションに従って特定の機能を起動する大きなフレームワークを使用しています。 この関数のコードを変更せずに、この関数を呼び出すイベントでコードを実行したいです。 練習は最高とはほど遠いです。関数呼び出しイベントは存在しません。寺で指をひねっただけで、それはひどいたわごとであると言いました、それをする価値はありません、これは単純に不可能です。



数日前、オデッサの典型ではない比較的暖かい冬の夜に家に帰るとき、私は「6か月前にボグダンが尋ねたことをやってみたらどうだろう? 家に着いて、私はコンピューターの電源を入れ、数分以内に、私が計画していたことをしました。 まず、組み込みメソッドが再定義された場合の動作に興味があり、その後、再定義前の以前の状態を何らかの方法で思い出すことができます。 オブジェクトが再定義された場合、その参照は破棄されず、以前の外観が保持されることを知っていました。 組み込み関数に関しては、疑問がありました。 それはあなたができることが判明しました。



ほとんどの場合、そのようなツールを使用する必要はありませんが、純粋に仮説的に、誰かが関数の呼び出しを追跡するタスクを持ち、各呼び出しでレポートを受け取り、

  1. 実行結果
  2. 渡された引数
  3. 呼び出しのコンテキスト(呼び出し時のこれは何ですか)
  4. ハンドラー作成後の関数呼び出しの数


(このリストは、ハンドラーに渡される引数と完全に一致しています)



addCallListener = function(func, callback){ var callNumber = 0; return function(){ var args = [].slice.call(arguments); var result; try { result = func.apply(this, arguments); callNumber++; } catch (e) { callback(e, args, this, callNumber); throw e; } callback(result, args, this, callNumber); return result; } }
      
      







非常にシンプルで簡潔ですね。



次に、いくつかの関数を次のように再定義します。



 someFunct = addCallListener(someFunct, function(result, args, self, callNumber){ //Do Something }); //  Constructor.prototype.method = addCallListener(Constructor.prototype.method, function(result, args, self, callNumber){ //Do Something });
      
      







明らかに、これが発生するコードのその部分で「見える」はずです。



いくつかの例
例を実行するには、開いているコンソールが必要です(ChromeではCtrl + Shift + iで呼び出されます)。



アニメーション追跡:

jsfiddle.net/finom/DnRD8

配列内のプッシュメソッド実行のイベント:

jsfiddle.net/finom/bbHhH/1

他の機能の実行イベント:

jsfiddle.net/finom/ah5My/3



終わり。



批評と追加についてjavascript.ruフォーラムの仲間に感謝します。



UPD

関数を少し拡張しました。1つのコールバックではなく、2番目の引数がオブジェクトになりました

  1. before(関数が実行される前に呼び出されます)
  2. 成功(関数が正常に機能した場合に呼び出されます)
  3. エラー(エラーが発生した場合)
  4. 後(とにかく、成功に関係なく呼び出されます)


オブジェクトは各ハンドラーに渡されます。

  1. args
  2. 自己(コンテキスト)
  3. name(関数名)
  4. ステータス(「エラー」または「成功」)
  5. successNumber(成功した呼び出しの数)
  6. errorNumber(エラーのある呼び出しの数)
  7. 結果(結果がある場合)
  8. エラー(エラーがある場合)


また、addCallListener関数は、ウィンドウまたはプロセスへのアクセスを回避するために、Functionコンストラクターオブジェクトの一部になりました。



ここで分岐およびテストできます: jsfiddle.net/finom/SGhzd/5



All Articles