JavaScript에서 현재 실행중인 함수의 이름을 얻을 수 있습니까?


184

이것을 할 수 있습니까?

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 엄격 모드에서 중단합니다.
— Raynos

4
아 .. 그래서 사람들은 항상 대답하는 속도로 나를 이겼습니다. 나는 그것을 생각하지 않았다.
— Erik Reppen

9
메소드에 객체 리터럴을 사용하고 실제 메소드 이름이 없으면 인수로 작동하지 않습니다. callee는 함수 이름을 포함하지 않는 익명 함수처럼 작동합니다. 해당 기능 이름을 두 번 추가해야합니다. 이 jsfiddle 예를 살펴 보자 : jsfiddle.net/ncays를 . 그러나 이것의 또 다른 문제 arguments.callee는 엄격 모드에서는 허용되지 않는다는 것입니다.
— 헬라 탄

75

비 익명 함수

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

그러나 오류 처리기의 경우 결과는 오류 처리기 함수의 이름이됩니까?


2
Chrome에서 잘 작동합니다. 허용 된 답변보다 훨씬 낫습니다.
— B Seven

1
마음에 가치 베어링 : eslint.org/docs/rules/no-caller은 > "자바 스크립트의 미래 버전에서 사용되지 않는 자신의 사용은 동안 엄격한 모드 인 ECMAScript 5에서 금지되어 있습니다."
— 제레미

44

필요한 것은 간단합니다. 함수 만들기 :

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

그런 다음 필요할 때마다 다음을 사용하십시오.

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

foo() 
// Logs: "foo"

3
고마워, 이것은 문자열을 파싱하는 것보다 훨씬 우아합니다.
— modle13

1
가장 좋은 답변 인 것 같습니다!
— Sergey

완전한. PHP가 매직 상수를 사용하는 것처럼 JS가 네이티브 상수를 가지고 있지 않을 때입니다.
— stamster

발신자에 'name'속성이 없으므로 Chrome에서 유형 오류가 발생합니다. 그러나, 검사 결과는 다음과 같이 작동 함이 밝혀졌습니다.function getFuncName() { return getFuncName.name }
— Tom Anderson

@TomAnderson이 변경되면 이제 getFuncName발신자 의 이름이 아닌 이름을 얻습니다 .
— 마크 맥 케나

30

MDN 에 따르면

경고 : ECMAScript (ES5) 5 판에서는 엄격 모드에서 arguments.callee ()를 사용할 수 없습니다. 함수 표현식에 이름을 지정하거나 함수 자체를 호출해야하는 함수 선언을 사용하여 arguments.callee ()를 사용하지 마십시오.

언급했듯이 이것은 스크립트가 "엄격 모드"를 사용하는 경우 에만 적용 됩니다 . 이것은 주로 보안상의 이유이며 슬프게도 현재로서는 이에 대한 대안이 없습니다.


21

이것은해야합니다 :

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

발신자의 경우을 사용하십시오 caller.toString().


8
이것은 나를 위해 일했지만 정규 표현식에 오타가 있다고 생각합니다. [
— 12

4
@ declan : 네, 그렇습니다. 거의 3 년 동안이 해답이 여기에 있다고 지적한 사람은 아무도 없습니다.
— Andy E

@AndyE는 아마 정규 표현식을 본 후에 TL; DR 모드로 들어가서 다른 답을 찾는다;)
— BitTickler

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 Function # caller는 비표준 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
— Max 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);
  });

});

세 번째 테스트는 테스트가 / 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 엄격 모드에서는 허용되지 않습니다 하고 Function.prototype.caller있다 비표준 및 엄격한 모드에서 사용할 수 없습니다 .


함수에서 위치를 표시하고 익명 함수를 지원하도록 확장하십시오. ?))? $ / g, '$ 1 ($ 2 : $ 3)')
— kofifus

엄격 모드에서는 Function.prototype.caller도 사용할 수 없습니다.
— fijiaaron

1
화살표 기능, 저평가 답변에도 완벽하게 작동
— Hao Wu

3

다른 유스 케이스는 런타임에 바인드 된 이벤트 디스패처 일 수 있습니다.

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 () 선택적 콜백과 같은 많은 경우에 유용 할 수 있습니다. 또는 타임 아웃 / 간격 콜백에서 (즉, 함수 NAME 만 전달).


2

이 질문이 제기 된 이후 현재 기능의 이름과 획득 방법은 지난 10 년 동안 변한 것 같습니다.

이제는 모든 브라우저의 모든 역사를 알고있는 프로 웹 개발자가 아니라 2019 크롬 브라우저에서 어떻게 작동하는지 알려줍니다.

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

다른 답변 중 일부는 엄격한 자바 스크립트 코드 및 기타에 대한 크롬 오류가 발생했습니다.


1

이름이 지정된 함수를 작성했기 때문에 foo당신은 그것을에 알고 myfile.js동적으로이 정보를 얻을 필요가 왜?

그것은 arguments.callee.toString()함수 내부에서 사용할 수 있으며 (이것은 전체 함수의 문자열 표현입니다) 함수 이름의 값을 정규식으로 표현하십시오.

다음은 자체 이름을 뱉어내는 함수입니다.

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

5
오류 처리기에서 작업 중이며 호출 함수를보고하고 싶습니다.
— sprugman 2016 년

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 피들 데모 : 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
})();

글자체 변형 :

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

이 Igor Ostroumov의 변종 답변 .

매개 변수의 기본값으로 사용하려면 'caller'에 대한 두 번째 레벨 호출을 고려해야합니다.

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"은 프랑스어로 "name"입니다. 이러한 종류의 세부 사항은 언어 버전의 브라우저간에 변경됩니까? 나는 그렇게 생각하지 않을 것입니다.
— argyle
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.