JavaScriptで現在実行中の関数の名前を取得できますか?


185

これを行うことは可能ですか?

myfile.js:
function foo() {
    alert(<my-function-name>);
    // pops-up "foo"
    // or even better: "myfile.js : foo"
}

私のスタックにはDojoフレームワークとjQueryフレームワークがあるので、どちらかを使用すると簡単に使用できるようになります。

回答:


196

ES5以降では、その情報にアクセスできません。

古いバージョンのJSでは、を使用して取得できますarguments.callee

ただし、追加のジャンクが含まれている可能性があるため、名前を解析する必要がある場合があります。ただし、一部の実装では、を使用して名前を簡単に取得できますarguments.callee.name

解析:

function DisplayMyName() 
{
   var myName = arguments.callee.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));

   alert(myName);
}

ソース:Javascript-現在の関数名を取得します


実際、実際に質問にもっと注意を払って、余分なジャンクが欲しくなるかもしれません:)
Matt

23
@Andrew-あなたは正しい、私はそれを述べるべきだった。それは私が既にブックマークしたものの簡単なコピー/貼り付け/クリーンアップであり、私の側の見落としでした。私の投稿に追加していただきありがとうございます。
Matt

81
ES5 strictモードで中断します。
レイノス2011

4
ああ...だからこそ、人々はいつも返信するスピードで私を倒しました。私はそのことを考えていませんでした。
エリック・レッペン、2012

9
メソッドにオブジェクトリテラルを使用していて、実際のメソッド名を使用していない場合、これは引数として機能しません。calleeは、関数名を持たない無名関数のように機能します。その関数名を2回追加する必要があります。このjsfiddleの例を見てください:jsfiddle.net/ncays。ただし、これに関する別の問題は、arguments.callee厳密モードでは許可されないことです。
hellatan 2013年

75

非匿名関数の場合

function foo()
{ 
    alert(arguments.callee.name)
}

しかし、エラーハンドラーの場合、結果はエラーハンドラー関数の名前になりますよね。


2
Chromeでうまく動作します。受け入れられた答えよりもはるかに良い。
Bセブン

1
念頭に置く価値がある:eslint.org/docs/rules/no-caller > "JavaScriptの将来のバージョンでは非推奨であり、厳密モードのECMAScript 5ではその使用は禁止されています。"
ジェレミー

44

必要なものはすべてシンプルです。関数を作成します。

function getFuncName() {
   return getFuncName.caller.name
}

その後、必要なときにいつでも使用できます。

function foo() { 
  console.log(getFuncName())
}

foo() 
// Logs: "foo"

3
おかげで、これは文字列を解析するよりもはるかにエレガントです。
modle13 2018年

1
正解のようです!
セルゲイ

完璧です。これは、JSにPHPのマジック定数のようにネイティブ定数がない場合です
stamster

プロパティ 'name'が呼び出し元に存在しないため、Chromeにタイプエラーが表示されます。しかし、検査は、これが働いていたことを明らかにした:function getFuncName() { return getFuncName.name }
トム・アンダーソン

@TomAndersonに変更を加えるとgetFuncName、呼び出し元の名前ではなく、名前が取得されます。
マークマッケナ

30

MDNによると

警告: ECMAScript(ES5)の第5版は、strictモードでのarguments.callee()の使用を禁止しています。関数式に名前を付けるか、関数がそれ自体を呼び出す必要がある関数宣言を使用して、arguments.callee()の使用を避けます。

すでに述べたように、これはスクリプトが "strictモード"を使用する場合にのみ適用されます。これは主にセキュリティ上の理由によるものであり、残念ながら現在のところこれに代わるものはありません。


21

これはそれを行うはずです:

var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);

発信者は、単にを使用しますcaller.toString()


8
これは私にとってはうまくいきましたが、私はあなたの正規表現にタイプミスがあると思います。私は前にバックスラッシュを取らなければならなかった[
デクラン

4
@declan:うん、そうだね。驚くべきことですが、ほぼ3年間でこの答えがここにあることを他の誰も指摘していません:-)
Andy E

@AndyEはおそらくそれを指摘しませんでした。正規表現が
見つかる

11

これは「世界で最も醜いハック」の範疇に入りますが、ここに行きます。

まず、現在の名前を出力します関数の(他の回答のように)ことは、関数が何であるかをすでに知っているので、私には使用が制限されているようです!

ただし、呼び出し元の関数の名前を見つけることは、トレース関数にはかなり役立ちます。これは正規表現を使用していますが、indexOfを使用すると約3倍高速になります。

function getFunctionName() {
    var re = /function (.*?)\(/
    var s = getFunctionName.caller.toString();
    var m = re.exec( s )
    return m[1];
}

function me() {
    console.log( getFunctionName() );
}

me();

ソリューションを冷却するが、FYIファンクション#の呼び出し側が非標準であるdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
マックスHeiber

現在の関数の名前を知ることは、その関数がデータベースから動的に作成されており、関数名に関連付けられた関数内のコンテキスト情報が必要な場合に不可欠です。
Paul Chernoch

9

これが機能する方法です:

export function getFunctionCallerName (){
  // gets the text between whitespace for second part of stacktrace
  return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}

次に、テストで:

import { expect } from 'chai';
import { getFunctionCallerName } from '../../../lib/util/functions';

describe('Testing caller name', () => {

    it('should return the name of the function', () => {
      function getThisName(){
        return getFunctionCallerName();
      }

      const functionName = getThisName();

      expect(functionName).to.equal('getThisName');
    });

  it('should work with an anonymous function', () => {


    const anonymousFn = function (){
      return getFunctionCallerName();
    };

    const functionName = anonymousFn();

    expect(functionName).to.equal('anonymousFn');
  });

  it('should work with an anonymous function', () => {
    const fnName = (function (){
      return getFunctionCallerName();
    })();

    expect(/\/util\/functions\.js/.test(fnName)).to.eql(true);
  });

});

3番目のテストは、テストが/ util / functionsにある場合にのみ機能することに注意してください。


7

getMyName以下のスニペットの関数は、呼び出し元の関数の名前を返します。これはハックであり、非標準機能に依存していますError.prototype.stack。によって返される文字列の形式は、Error.prototype.stackエンジンによって実装方法が異なるため、これがおそらくどこでも機能しないことに注意してください。

function getMyName() {
  var e = new Error('dummy');
  var stack = e.stack
                .split('\n')[2]
                // " at functionName ( ..." => "functionName"
                .replace(/^\s+at\s+(.+?)\s.+/g, '$1' );
                return stack
}

function foo(){
  return getMyName()
}

function bar() {
  return foo()
}

console.log(bar())

他のソリューションについて:arguments.callee strictモードFunction.prototype.caller許可されておらず、非標準であり、strictモードでは許可されていません


これを拡張して、関数内の位置も表示し、無名関数をサポートします。 ?))?$ / g、 '$ 1($ 2:$ 3)')
kofifus

Function.prototype.callerもstrictモードでは許可されていません。
fijiaaron

1
アロー機能にも完璧に動作し、過小評価された回答
Hao Wu

3

もう1つの使用例は、実行時にバインドされるイベントディスパッチャーです。

MyClass = function () {
  this.events = {};

  // Fire up an event (most probably from inside an instance method)
  this.OnFirstRun();

  // Fire up other event (most probably from inside an instance method)
  this.OnLastRun();

}

MyClass.prototype.dispatchEvents = function () {
  var EventStack=this.events[GetFunctionName()], i=EventStack.length-1;

  do EventStack[i]();
  while (i--);
}

MyClass.prototype.setEvent = function (event, callback) {
  this.events[event] = [];
  this.events[event].push(callback);
  this["On"+event] = this.dispatchEvents;
}

MyObject = new MyClass();
MyObject.setEvent ("FirstRun", somecallback);
MyObject.setEvent ("FirstRun", someothercallback);
MyObject.setEvent ("LastRun", yetanothercallback);

ここでの利点は、ディスパッチャーを簡単に再利用でき、ディスパッチキューを引数として受け取る必要がないことです。代わりに、呼び出し名が暗黙的に指定されます...

結局、ここで提示される一般的なケースは「関数名を引数として使用するため、明示的に渡す必要がない」ということであり、jquery animate()オプションのコールバックなど、多くの場合に役立ちます。またはタイムアウト/インターバルのコールバックで(つまり、関数名のみを渡します)。


2

現在の関数の名前とその取得方法は、この質問が出されてから過去10年間で変わったようです。

さて、これまで存在していたすべてのブラウザーのすべての履歴を知っているプロのWeb開発者ではなく、2019 Chromeブラウザーでの私にとっての動作は次のとおりです。

function callerName() {
    return callerName.caller.name;
}
function foo() {
    let myname = callerName();
    // do something with it...
}

他の回答のいくつかは、厳密なJavaScriptコードなどに関するChromeエラーに遭遇しました。


1

という名前の関数を記述していて、そのため、この情報を動的に取得する必要fooがあるのはmyfile.jsなぜですか。

arguments.callee.toString()関数内(これは関数全体の文字列表現です)で使用でき、関数名の値を正規表現できます。

以下は、独自の名前を吐き出す関数です。

function foo() {
    re = /^function\s+([^(]+)/
    alert(re.exec(arguments.callee.toString())[1]);             
}

5
エラーハンドラの作業をしていて、呼び出し元の関数を報告したいと思います。
スプラグマン09年

1

ここで見たいくつかの応答の組み合わせ。(FF、Chrome、IE11でテスト済み)

function functionName() 
{
   var myName = functionName.caller.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));
   return myName;
}

function randomFunction(){
    var proof = "This proves that I found the name '" + functionName() + "'";
    alert(proof);
}

randomFunction()を呼び出すと、関数名を含む文字列が警告されます。

JS Fiddleデモ:http : //jsfiddle.net/mjgqfhbe/



1

情報は2016年実績です。


関数宣言の結果

オペラの結果

>>> (function func11 (){
...     console.log(
...         'Function name:',
...         arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
... 
... (function func12 (){
...     console.log('Function name:', arguments.callee.name)
... })();
Function name:, func11
Function name:, func12

クロムの結果

(function func11 (){
    console.log(
        'Function name:',
        arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
})();

(function func12 (){
    console.log('Function name:', arguments.callee.name)
})();
Function name: func11
Function name: func12

NodeJSの結果

> (function func11 (){
...     console.log(
.....         'Function name:',
.....         arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
Function name: func11
undefined
> (function func12 (){
...     console.log('Function name:', arguments.callee.name)
... })();
Function name: func12

Firefoxでは機能しません。IEとEdgeでテストされていません。


関数式の結果

NodeJSの結果

> var func11 = function(){
...     console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11

クロムの結果

var func11 = function(){
    console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11

Firefox、Operaでは機能しません。IEとEdgeでテストされていません。

ノート:

  1. 匿名関数はチェックしても意味がありません。
  2. テスト環境

~ $ google-chrome --version
Google Chrome 53.0.2785.116           
~ $ opera --version
Opera 12.16 Build 1860 for Linux x86_64.
~ $ firefox --version
Mozilla Firefox 49.0
~ $ node
node    nodejs  
~ $ nodejs --version
v6.8.1
~ $ uname -a
Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

1
(function f() {
    console.log(f.name);  //logs f
})();

Typescriptバリエーション:

function f1() {} 
function f2(f:Function) {
   console.log(f.name);
}

f2(f1);  //Logs f1

ES6 / ES2015準拠のエンジンでのみ使用できることに注意してください。 詳しくは


0

ここにワンライナーがあります:

    arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')

このような:

    function logChanges() {
      let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
      console.log(whoami + ': just getting started.');
    }

0

これはイゴールオストロウモフの変形です答えの:

これをパラメーターのデフォルト値として使用する場合は、「caller」の第2レベルの呼び出しを検討する必要があります。

function getFunctionsNameThatCalledThisFunction()
{
  return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}

これにより、動的に複数の関数で再利用可能な実装が可能になります。

function getFunctionsNameThatCalledThisFunction()
{
  return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}

function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{ 
  alert(myFunctionName);
}

// pops-up "foo"
function foo()
{
  bar();
}

function crow()
{
  bar();
}

foo();
crow();

ファイル名も必要な場合は、別の質問に対するF-3000からの回答を使用した解決策を次に示します。

function getCurrentFileName()
{
  let currentFilePath = document.scripts[document.scripts.length-1].src 
  let fileName = currentFilePath.split('/').pop() // formatted to the OP's preference

  return fileName 
}

function bar(fileName = getCurrentFileName(),  myFunctionName = getFunctionsNameThatCalledThisFunction())
{
  alert(fileName + ' : ' + myFunctionName);
}

// or even better: "myfile.js : foo"
function foo()
{
  bar();
}


-7

答えは短いです: alert(arguments.callee.name);


12
「nom」はフランス語で「名前」です。この種の詳細は、ブラウザーの言語バージョンによって異なりますか?私はそうは思いません。
アーガイル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.