2011-12-13 17 views
5

私は多くのオブジェクトと関数(オブジェクトメソッド)からなるjavascriptアプリケーションを開発しています。私は、アプリケーションのライフサイクルで多くのイベントを記録できるようにしたいと考えています。私の問題は、ロガー内では、どの機能がログエントリを呼び出したのかを知りたいので、そのデータをログメッセージとともに保存することができます。これは、すべての関数が何らかの形で自身を参照できる必要があることを意味するので、その参照をロガーに渡すことができます。 javascript strictモードを使用しているため、関数内でarguments.calleeを使用することはできません。独自の実装から関数を参照するには?

ここでは、実行できる非常に単純化されたコードサンプルを示します。私は簡単にするために私のロガーの代わりにここでalertを使用しています。最初の警告で

(function(){ 
"use strict"; 

window.myObject = { 
    id : 'myObject', 
    myFunc : function(){ 
     alert(this.id); // myObject 
     alert(this.myFunc.id); // myFunc - I don't want to do this. I want something generic for all functions under any object 
     alert('???') // myFunc 
     alert(arguments.callee.id); // Will throw an error because arguments.callee in not allowed in strict mode 
    } 
} 
myObject.myFunc.id = 'myFunc'; 

myObject.myFunc(); 
})(); 
  1. - this二Iの警告でmyFunc
  2. myObjectずに関連する - 私は私のように、私はしたくない、その名前によって機能を参照しました独自の実装から関数を参照する一般的な方法を探しています。
  3. 3番目のアラート - あなたのアイデアを公開します。
  4. 第4のアラートは、私が"use stict";を入力しなかった場合にはうまくいったでしょう。私はより良いパフォーマンスを提供するので、厳密なモードを維持したい、良いコーディング練習を構成します。

すべての入力をいただければ幸いです。

あなたが「strictモード」に慣れていない場合は、これはそれについて読むには良い場所です: JavaScript Strict Mode

答えて

4

は、ここでそれを行うための非常にハック方法です:

(function(){ 
    "use strict"; 
    window.myObject = { 
     id: 'myObject', 
     myFunc: function() { 
      // need this if to circumvent 'use strict' since funcId doesn't exist yet 
      if (typeof funcId != 'undefined') 
       alert(funcId); 
     }, 
     myFunc2: function() { 
      // need this if to circumvent 'use strict' since funcId doesn't exist yet 
      if (typeof funcId != 'undefined') 
       alert(funcId); 
     } 
    } 
    // We're going to programatically find the name of each function and 'inject' that name 
    // as the variable 'funcId' into each function by re-writing that function in a wrapper 
    for (var i in window.myObject) { 
     var func = window.myObject[i]; 
     if (typeof func === 'function') { 
      window.myObject[i] = Function('var funcId = "' + i + '"; return (' + window.myObject[i] + ')()'); 
     } 
    } 

    window.myObject.myFunc(); 
    window.myObject.myFunc2(); 
})(); 

を基本的に、我々はその関数の名前を見つけた後、我々は文字列から各機能を再コンパイルすることで「を使用し、厳格な」宣言を回避しています。これを行うために、変数が関数closure内の関数に公開されるように、ターゲット関数の名前と同じ文字列変数 'funcId'を宣言する各関数のラッパーを作成します。

私は、物事を行う最良の方法ではありませんが、機能します。支援を期待

(function(){ 
    "use strict"; 

    window.myObject = { 
     id: 'myObject', 
     myFunc: function() { 
      alert(getFuncName()) 
     }, 
     myFunc2: function() { 
      alert(getFuncName()); 
     } 
    } 
})(); 

// non-strict function here 
function getFuncName(){ 
    return arguments.callee.caller.id; // Just fyi, IE doesn't have id var I think...so you gotta parse toString or something 
} 

また、あなたは単に内から非厳格な関数を呼び出すことができます。

+0

ありがとう!それらはクールなソリューションです:) –

0
myFunc : function _myFunc(){ 
    alert(_myFunc); // function 
} 

は、あなたのログの目的を解決するために、あなたの関数に名前を付け、直接

それらを参照します本当の意味のあるユニークなロギングメッセージを使用してください。行情報が必要な場合は、例外をスローします。

+1

もっと一般的なものを探していますので、必ずしもその名前で各機能を参照する必要はありません。 「this」のように文脈を参照し、私は文脈の名前を使用する必要はありません。 –

+0

@OrrSiloniは存在しません。関数名を使用します。それに、あなたのすべての機能には名前が必要です。 – Raynos

+0

私は、関数の名前をロガーに渡すことから脱出できないと考え始めています。まだ誰かが私を驚かせるだろうと願っています。 –

0

私はあなたがしたいと思っていません(現在の関数の名前を見つける)はとても簡単です。

function logger(id){ return function(msg){ 
    return console.log(id, msg); 
};} 

window.myObject = { 
    id : 'myObject', 
    myFunc : function(){ 
     var log = logger('myFunc'); 

     log(1); //prints "Myfunc, 1" 
     log(2); //prints "Myfunc, 2" 
    } 
}; 

これは警官アウトのようなものですが、ある:あなたは魔法をカリー化することはトリックがない/(Cで__line__のようなもののために行われているような)前処理工程を追加することに見えますが、おそらくほんの少しOOする場合があります非常にシンプルで、IDと関数名を順番に覚えておけば妥当な結果が得られます。

+0

これは良いアプローチですが、すべての関数の開始時に常にロガーを呼び出し、関数の名前を文字列として渡す必要があります。これは、まずは避けようとしていたものです。 –

+0

@OrrSiloni:私は知っていますが、少なくともあなたは一度だけそれをやらなければならず、同じ関数内に名前がなく、複数の名前を持つ匿名関数でも動作します。 – hugomg

関連する問題