क्या मुझे जावास्क्रिप्ट में वर्तमान में चल रहे फ़ंक्शन का नाम मिल सकता है?


184

क्या इसे करना संभव है:

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

मुझे अपने स्टैक में Dojo और jQuery फ्रेमवर्क मिले हैं, इसलिए यदि उनमें से कोई भी इसे आसान बनाता है, तो वे उपलब्ध हैं।

जवाबों:


196

ES5 और इसके बाद के संस्करण में, उस जानकारी तक पहुंच नहीं है।

जेएस के पुराने संस्करणों में आप इसका उपयोग करके प्राप्त कर सकते हैं 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);
}

स्रोत: जावास्क्रिप्ट - वर्तमान फ़ंक्शन नाम प्राप्त करें


वास्तव में, वास्तव में आपके प्रश्न पर अधिक ध्यान देना, ऐसा लगता है कि आप अतिरिक्त जंक चाहते हैं :)
मैट

23
@ और - आप सही हैं, मुझे यह कहना चाहिए था। यह एक त्वरित कॉपी / पेस्ट / क्लीनअप था जिसे मैंने पहले से ही बुकमार्क कर लिया था, और मेरी ओर से एक निरीक्षण। इसे मेरी पोस्ट में शामिल करने के लिए धन्यवाद।
मैट

81
ईएस 5 सख्त मोड में टूट जाता है।
रेयानोस

4
ओह ... इसीलिए लोगों ने हमेशा मुझे जवाब देने की गति से हराया। मैंने ऐसा नहीं सोचा था।
एरिक रिपन

9
यदि आप अपने तरीकों और कोई वास्तविक विधि नाम के लिए एक ऑब्जेक्ट शाब्दिक का उपयोग कर रहे हैं, तो यह तर्क के रूप में काम नहीं करेगा। कुछ अनाम फ़ंक्शन की तरह कार्य करता है जो किसी फ़ंक्शन का नाम नहीं लेगा। आपको यह सुनिश्चित करना होगा कि आप उस फ़ंक्शन का नाम दो बार जोड़ दें। इस jsfiddle उदाहरण पर एक नज़र डालें: jsfiddle.net/ncays । हालांकि, इसके साथ एक और मुद्दा arguments.calleeसख्त मोड के तहत अनुमति नहीं है।
हेलातन

75

गैर-अनाम कार्यों के लिए

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

लेकिन एक त्रुटि हैंडलर के मामले में परिणाम त्रुटि हैंडलर फ़ंक्शन का नाम होगा, है ना?


2
क्रोम में महान काम करता है। स्वीकृत उत्तर की तुलना में बहुत बेहतर है।
बी सेवन

1
ध्यान में रखते हुए असर: eslint.org/docs/rules/no-caller > "जावास्क्रिप्ट के भविष्य के संस्करणों में चित्रित किया गया है और उनका उपयोग ECMAScript 5 में सख्त मोड में मना किया गया है।"
जेरेमी

45

आप सभी की जरूरत है सरल है। समारोह बनाएँ:

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

इसके बाद जब भी आपको आवश्यकता हो, आप बस उपयोग करें:

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

foo() 
// Logs: "foo"

3
धन्यवाद, यह एक स्ट्रिंग को पार्स करने की तुलना में बहुत अधिक सुरुचिपूर्ण है।
modle13

1
यह सबसे अच्छा जवाब लगता है!
सेर्गेई

उत्तम। जब JS के पास
स्थैतिक

Chrome मुझे एक प्रकार की त्रुटि देता है क्योंकि कॉलर पर संपत्ति 'नाम' मौजूद नहीं है। हालांकि, निरीक्षण से पता चला कि यह काम किया:function getFuncName() { return getFuncName.name }
टॉम एंडरसन

@TomAnderson अपने परिवर्तन के साथ, अब आपको getFuncNameइसके कॉलर के नाम के बजाय नाम मिल रहा है ।
मार्क मैककेना

30

एमडीएन के अनुसार

चेतावनी: ECMAScript (ES5) के 5 वें संस्करण का उपयोग तर्कों का उपयोग करता है। तर्कों का उपयोग करने से बचें। (या तो फ़ंक्शन एक्सप्रेशन को एक नाम देकर या फ़ंक्शन डिक्लेरेशन का उपयोग करें जहां फ़ंक्शन को स्वयं कॉल करना होगा।

जैसा कि कहा गया है कि यह तभी लागू होता है जब आपकी स्क्रिप्ट "सख्त मोड" का उपयोग करती है। यह मुख्य रूप से सुरक्षा कारणों से है और दुख की बात है कि वर्तमान में इसके लिए कोई विकल्प नहीं है।


21

यह करना चाहिए:

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

कॉलर के लिए, बस का उपयोग करें caller.toString()


8
यह मेरे लिए काम करता है लेकिन मुझे लगता है कि आपके regexp में एक टाइपो है। मुझे इससे पहले बैकस्लैश निकालना था[
डिकेल

4
@declan: हाँ, आप सही कह रहे हैं। यह आश्चर्य की बात है कि किसी और ने यह नहीं बताया है कि लगभग 3 वर्षों में यह उत्तर यहाँ दिया गया है :-)
एंडी ई

@AndyE शायद किसी ने इसे इंगित नहीं किया क्योंकि एक बार जब हम एक regexp देखते हैं, तो हम TL में प्रवेश करते हैं; DR मोड और अन्य उत्तरों की तलाश करते हैं;)
22

11

इसके लिए "दुनिया की सबसे बदसूरत हैक्स" की श्रेणी में जाना पड़ता है, लेकिन यहां आप जाते हैं।

सबसे पहले, करंट का नाम प्रिंट करना फ़ंक्शन (जैसा कि अन्य उत्तरों में है) करना मुझे सीमित उपयोग लगता है, क्योंकि आप पहले से ही जानते हैं कि फ़ंक्शन क्या है!

हालाँकि, कॉलिंग फ़ंक्शन का नाम पता लगाना ट्रेस फ़ंक्शन के लिए बहुत उपयोगी हो सकता है। यह एक regexp के साथ है, लेकिन indexOf का उपयोग करना लगभग 3x तेज होगा:

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 करें फंक्शन # कॉलर गैर-मानक डेवलपर.
mozilla.org/en-US/docs/Web/JavaScript/Reference/…

वर्तमान फ़ंक्शन के नाम को जानना आवश्यक हो सकता है अगर उस फ़ंक्शन को गतिशील रूप से डेटाबेस से बनाया जा रहा है और फ़ंक्शन के नाम के संदर्भ में संदर्भ जानकारी की आवश्यकता है।
पॉल चेरोच

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);
  });

});

ध्यान दें कि तीसरा परीक्षण केवल तभी काम करेगा जब परीक्षण / उपयोग / कार्यों में स्थित हो


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है अमानक और सख्त मोड में अनुमति नहीं


फ़ंक्शन में स्थिति दिखाने और अनाम कार्यों के साथ समर्थन करने के लिए इसे बढ़ाएँ: .replace (/ ^ \ s + at \ s (??) ?: ?: \ s। *: |:) ((? *?): (। *) ;)); $ / g, '$ 1 ($ 2: $ 3)')
kofifus

फ़ंक्शन .prototype.caller को भी सख्त मोड में अनुमति नहीं है।
फिजियारॉन

1
एरो फ़ंक्शंस, अंडररेटेड उत्तर के लिए भी सही काम करता है
हाओ वू

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);

यहाँ लाभ यह है कि डिस्पैचर को आसानी से पुन: उपयोग किया जा सकता है और एक तर्क के रूप में डिस्पैच कतार प्राप्त नहीं करना है, इसके बजाय यह आह्वान नाम के साथ आता है ...

अंत में, यहां प्रस्तुत सामान्य मामला "फ़ंक्शन नाम का उपयोग एक तर्क के रूप में किया जाएगा ताकि आपको इसे स्पष्ट रूप से पास न करना पड़े", और यह कई मामलों में उपयोगी हो सकता है, जैसे कि ज्यूरी चेतन () वैकल्पिक कॉलबैक, या समयबाह्य / अंतराल कॉलबैक में, (यानी आप केवल एक मजेदार 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
मैं एक त्रुटि हैंडलर पर काम कर रहा हूं, और मैं कॉलिंग फ़ंक्शन की रिपोर्ट करना चाहता हूं।
जुगनू

1

कुछ प्रतिक्रियाओं का एक संयोजन मैंने यहाँ देखा है। (एफएफ, क्रोम, 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);
}

रैंडम फंक्शन () कॉलिंग एक स्ट्रिंग को अलर्ट करेगा जिसमें फ़ंक्शन नाम शामिल है।

जेएस फिडेल डेमो: http://jsfiddle.net/mjgqfhbe/


1

इस पर एक अद्यतन उत्तर इस उत्तर पर पाया जा सकता है: https://stackoverflow.com/a/2161470/632495

और, यदि आपको क्लिक करने का मन नहीं है:

function test() {
  var z = arguments.callee.name;
  console.log(z);
}

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

फ़ायरफ़ॉक्स में काम नहीं करता है। आईई और एज पर अनटाइटेड।


फ़ंक्शन अभिव्यक्तियों के लिए परिणाम

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

फ़ायरफ़ॉक्स, ओपेरा में काम नहीं करता है। आईई और एज पर अनटाइटेड।

टिप्पणियाँ:

  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

यह इगोर ओस्ट्रोवोव का एक प्रकार है उत्तर :

यदि आप इसे एक पैरामीटर के लिए डिफ़ॉल्ट मान के रूप में उपयोग करना चाहते हैं, तो आपको 'कॉलर' के लिए दूसरे स्तर के कॉल पर विचार करने की आवश्यकता है:

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
फ्रेंच में "नाम" "नाम" है। क्या ब्राउज़र के भाषा संस्करणों के बीच इस प्रकार का विस्तार होता है? मुझे ऐसा नहीं लगता।
argyle
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.