web-dev-qa-db-ja.com

JavaScriptで関数がどこから呼び出されているかを知る方法は?

関数がどこから呼び出されているかを見つけることは可能ですか?はいの場合、関数がから呼び出されているかどうかを検出する方法グローバルスコープ別の関数から、またはおそらくブラウザコンソールから?

次の例を見てください。

_<script>
    function myFunc1() {
        // some code
        myFunc2(); // I was called from myFunc1()
    }
    function myFunc2() {
        var callerName = new String;
        callerName = arguments.callee.caller.name;
        // some code
        alert('I was called from ' + callerName + ' function');
    }
    myFunc2(); // I was called from global scope
</script>
_

上記の例のこの行_callerName = arguments.callee.caller.name;_は、呼び出し元関数の名前を教えてくれることを知っています。しかし、わかりません関数がグローバルスコープから呼び出されたかどうかを検出する方法。たとえば、myFunc2()を変更し、_if else_ステートメントを追加して_arguments.callee.caller.name_はundefined値を返します。これは、関数がグローバルスコープから呼び出されたときに発生することを認識しています。

_myFunc2() {
var callerName = new String;
callerName = arguments.callee.caller.name;
    if(callerName == undefined) {
        alert('I was called from global scope');
    } else {
        alert('I was called from ' + callerName + ' function');
    }
}
_

ただし、myFunc2()がグローバルスコープから呼び出され、_callerName = arguments.callee.caller.name;_によってJavaScriptが次のエラーをスローする場合、これは機能しません。

_TypeError: 'null' is not an object (evaluating 'arguments.callee.caller.name')
_

だから私は正方形に戻りました、そして質問はまだ残っています:

  • 関数がグローバルスコープ?から呼び出されたかどうかを検出する方法
  • グローバルスコープから呼び出された場合、それはブラウザコンソール?からですか?
21
ilgaar

Chromeでは、次を使用できます。

console.trace();

その行を関数に追加するだけです。通常、最初の行として配置します。コンソールを表示すると、関数の名前が表示され、その行の下に、関数がどこから呼び出されているかが表示されます。

16
Gene Parcellano

関数がグローバルスコープから呼び出された場合、arguments.callee.caller.nameは未定義になります。それ以外の場合は、呼び出し元関数の名前になります(呼び出し元のスコープも表します)。

したがって、 厳密モード を除いて、すでに持っているものは機能するはずです。ここでarguments.callee 利用できません。


さらに、ブラウザから利用できる開発者ツールは、おそらくこの種のものを検査するためのより良い方法です。ブレークポイントを設定して、スタックトレースパネルを確認するだけです。もちろん、コード自体が実行時に呼び出しスコープを知る必要がない限り。

7
bfavaretto

ブラウザによっては、たとえばtry/catch内の未定義の変数にアクセスすることで、挑発してエラーが発生する可能性があります。次に、一部のブラウザがエラーで提供するスタックトレースを調べます。

これは非常にブラウザ固有です。

3
HBP
function func1() {
    // some code
    func2(); // I was called from func1()
}
function func2() {
var callerName = new String;
callerName = arguments.callee.caller ? arguments.callee.caller.name : "global";
    if(callerName == "global") {
        alert('I was called from global scope');
    } else {
        alert('I was called from ' + callerName + ' function');
    }
}
func1();
func2(); // I was called from global scope

func2が呼び出されると、呼び出し元の名前が表示され、別の関数スコープ内で呼び出された場合はその関数の名前が表示され、グローバルスコープから呼び出された場合は、グローバルスコープから呼び出されたことを示すメッセージが表示されます。

2
vickisys

JavaScriptでは、ほとんどのものはオブジェクトです。callerName = new Stringを宣言すると、いくつかのプロパティとメソッドを使用してstringオブジェクトを作成します。たとえば、valueOf()メソッドは、文字列オブジェクトのプリミティブ値を返します。 ただし、JavaScriptが示すように'TypeError: 'null' is not an objectnullはオブジェクトではありませんではなく、オブジェクトがないことです。 nullにはメソッドやプロパティがありません。関数がグローバルスコープから呼び出されると、arguments.callee.callerは呼び出し元をnullに評価します。Soarguments.callee.caller.nameは次のようになります。nullのnameプロパティ(null.nameにアクセスしようとしていますが、nullにはnameというプロパティがありません。オブジェクトではなく、できないためなんらかの財産を持っています。存在しないものにアクセスしようとしているため、JavaScriptが文句を言うのはこのためです。ただし、最初にcallerかどうかを確認することができます。は偽の値です単純なif elseステートメントを使用してif(!arguments.callee.caller)そうでない場合はnamecallerプロパティにアクセスして、どの関数を見つけることができますはmyFunc2()を呼び出しましたが、の場合、関数がグローバルスコープから呼び出されたことがわかります。

function myFunc2() {
    if(!arguments.callee.caller) {
        callerName = "global";
        alert('I was called from global scope');
    } else {
        callerName = arguments.callee.caller.name;
        alert('I was called from ' + callerName + ' function');
    }
}
1
ilgaar

それはかなり難しい質問です。この回答で説明されているように、Arguments.calleeは一部のブラウザーで非推奨になっています。

アプローチに応じて、Function.callerを使用できます。私はかなり書いています 簡単な例

function A() {
    if (A.caller === null || A.caller.name == "") console.log("Function called from top window")
    else console.log("Called from " + A.caller.name);
    B();
}

function B() {
    if (B.caller === null || B.caller.name == "") console.log("Function called from top window")
    else console.log("Called from " + B.caller.name);
}

A();

別のより一般的な例を見つけることができます ここ

それでも'use strict'はこれらのアプローチを両方とも失敗させるので、try / catchブロックを使用すると問題を解決できるか、関数の " ダミーコールスタック "をシミュレートできます(事実に応じて)すべてのコードが同期して機能すること)

1
vorillaz