Şu anda çalışan işlevin adını JavaScript'te alabilir miyim?


185

Bunu yapmak mümkün mü:

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

Yığımda Dojo ve jQuery çerçeveleri var, bu yüzden bunlardan herhangi birini kolaylaştırırsa kullanılabilirler.

Yanıtlar:


196

ES5 ve üzeri sürümlerde, bu bilgilere erişim yoktur.

JS'nin eski sürümlerinde bunu kullanarak alabilirsiniz arguments.callee.

Muhtemelen ekstra önemsiz içereceği için adı ayrıştırmanız gerekebilir. Yine de, bazı uygulamalarda kullanarak adı alabilirsiniz arguments.callee.name.

Ayrıştırma:

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

   alert(myName);
}

Kaynak: Javascript - geçerli işlev adını al .


Aslında, sorunuza daha fazla dikkat ederek, ekstra önemsiz isteyebileceğiniz gibi görünüyor :)
Matt

23
@Andrew - Haklısın, bunu söylemeliydim. Bu zaten yer imi vardı bir şey hızlı bir kopya / yapıştır / temizleme ve benim tarafımda bir gözetim oldu. Yazıma eklediğiniz için teşekkür ederim.
Matt

81
ES5 katı modda kırılır.
Raynos

4
Oh ... bu yüzden insanlar her zaman cevap verme hızında beni dövdüler. Bunu düşünmemiştim.
Erik Reppen

9
yöntemleriniz için bir nesne değişmezi kullanıyorsanız ve gerçek bir yöntem adı yoksa, bu arguments.callee işlevi herhangi bir işlev adı taşımayan anonim bir işlev gibi davranır. Bu işlev adını iki kez eklediğinizden emin olmanız gerekir. Şu jsfiddle örneğine bir göz atın: jsfiddle.net/ncays . Bununla birlikte başka bir sorun, arguments.calleekatı modda izin verilmemesidir.
hellatan

75

Anonim olmayan işlevler için

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

Ancak bir hata işleyici durumunda sonuç, hata işleyici işlevinin adı olur, değil mi?


2
Chrome'da harika çalışıyor. Kabul edilen cevaptan çok daha iyi.
B Seven

1
Unutulmamalıdır ki : eslint.org/docs/rules/no-caller > "JavaScript'in gelecekteki sürümlerinde kullanımdan kaldırıldı ve bunların kullanımı ECMAScript 5'de katı moddayken yasaktır."
Jeremy

44

İhtiyacınız olan her şey basit. Oluşturma işlevi:

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

Bundan sonra, ihtiyacınız olduğunda, şunları kullanırsınız:

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

foo() 
// Logs: "foo"

3
Teşekkürler, bu bir dizeyi ayrıştırmaktan çok daha zariftir.
modle13

1
En iyi cevap gibi görünüyor!
Sergey

Mükemmel. İşte o zaman PHP'nin Magic sabitleri ile yaptığı gibi PHP'nin yerel sabitleri yok ...
stamster

Arayanda 'name' özelliği bulunmadığından Chrome bana bir tür hatası veriyor. Ancak, teftiş bunun işe yaradığını ortaya koydu:function getFuncName() { return getFuncName.name }
Tom Anderson

@TomAnderson, değişikliğinizle, artık getFuncNamearayanın adından ziyade adını alıyorsunuz .
Mark McKenna

30

MDN'ye göre

Uyarı: ECMAScript'in (ES5) 5. sürümü, arguments.callee () işlevinin katı modda kullanılmasını yasaklar. İşlev ifadelerine bir ad vererek arguments.callee () yöntemini kullanmaktan kaçının veya bir işlevin kendisini çağırması gereken bir işlev bildirimi kullanın.

Belirtildiği gibi bu sadece betiğiniz "katı mod" kullanıyorsa geçerlidir . Bu esas olarak güvenlik nedenlerinden ötürü ve ne yazık ki şu anda bunun bir alternatifi yok.


21

Bunu yapmalı:

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

Arayan için sadece kullanın caller.toString().


8
Bu benim için çalıştı ama bence normal ifadenizde bir yazım hatası var. Daha önce ters eğik çizgiyi çıkarmak zorunda kaldım[
declan

4
@declan: evet, haklısın. Kimse neredeyse 3 yıl içinde bu cevabın burada olduğunu işaret etmedi şaşırtıcı
Andy E

@AndyE muhtemelen kimse işaret etmedi çünkü bir normal ifade gördüğümüzde TL giriyoruz; DR moduna giriyoruz ve diğer cevapları
buluyoruz

11

Bu "dünyanın en çirkin hackleri" kategorisine girmeli, ama işte gidiyorsunuz.

Öncelikle, mevcut işlevin adını yazdırmak (diğer yanıtlarda olduğu gibi) benim için sınırlı bir kullanım alanına sahip gibi görünüyor, çünkü işlevin ne olduğunu zaten biliyorsunuz!

Ancak, çağıran işlevin adını bulmak bir izleme işlevi için oldukça yararlı olabilir. Bu normal ifade ile, ancak indexOf kullanmak yaklaşık 3 kat daha hızlı olurdu:

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

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

me();

harika bir çözüm, ancak FYI İşlev # arayan standart olmayan bir geliştiricidir.
mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…

Geçerli işlevin adını bilmek, bu işlev bir veritabanından dinamik olarak oluşturuluyorsa ve işlev adına anahtarlanan işlev içinde bağlam bilgisine ihtiyaç duyuyorsa gerekli olabilir.
Paul Chernoch

9

İşte işe yarayacak bir yol:

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

Sonra testlerinizde:

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

});

Üçüncü testin yalnızca test / util / function konumunda bulunuyorsa çalışacağını unutmayın.


7

Aşağıdaki getMyNamesnippet'teki işlev, çağıran işlevin adını döndürür. Bu kesmek ve güvenir standart dışı özellik: Error.prototype.stack. Tarafından döndürülen dizenin biçiminin Error.prototype.stackfarklı motorlarda farklı şekilde uygulandığını unutmayın, bu muhtemelen her yerde çalışmaz:

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

Başka çözümler hakkında: arguments.callee katı modda izin verilmez ve Function.prototype.callerbir standart dışı ve sıkı modda izin verilmez .


işlevdeki konumu göstermek ve anonim işlevleri aşağıdakilerle desteklemek için uzatın: .replace (/ ^ \ s + at \ s (. +?) (?: \ s. *: |:) (. *?): (. * ?))? $ / g, '1 $ (2 $: 3 $)')
kofifus

Sıkı modda function.prototype.caller öğesine de izin verilmez.
fijiaaron

1
Ok fonksiyonları için bile mükemmel çalışıyor, yetersiz cevap
Hao Wu

3

Başka bir kullanım durumu, çalışma zamanında bağlı bir olay dağıtıcısı olabilir:

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

Buradaki avantaj, dağıtım programının kolayca yeniden kullanılabilmesi ve dağıtım sırasını bağımsız değişken olarak alması gerekmemesidir, bunun yerine çağrı adı ile örtülü olarak gelir ...

Sonunda, burada sunulan genel durum "işlev adını bir argüman olarak kullanmaktır, bu yüzden açıkça iletmeniz gerekmez" ve bu, jquery animate () isteğe bağlı geri çağırma, veya zaman aşımı / aralıklarla geri aramalarda (yani yalnızca bir NAME işlevi iletirsiniz).


2

Mevcut fonksiyonun adı ve nasıl elde edilebileceği, bu sorunun sorulduğu için son 10 yılda değişmiş gibi görünüyor.

Şimdiye kadar var olan tüm tarayıcıların tüm geçmişlerini bilen profesyonel bir web geliştiricisi olmak değil, 2019 chrome tarayıcısında benim için şu şekilde çalışıyor:

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

Diğer cevaplardan bazıları, sıkı javascript kodu ve ne olursa olsun bazı krom hataları ile karşılaştı.


1

Adında bir işlev yazdığınızdan foove bunun myfile.jsneden olduğunu bildiğinizden, bu bilgileri neden dinamik olarak almanız gerekiyor?

arguments.callee.toString()İşlev içinde kullanabilirsiniz (bu, tüm işlevin dize temsilidir) ve işlev adının değerini yeniden düzenleyebilirsiniz.

İşte kendi adını söyleyecek bir fonksiyon:

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

5
Bir hata işleyici üzerinde çalışıyorum ve arama işlevini bildirmek istiyorum.
sprugman

1

Burada gördüğüm birkaç yanıtın bir kombinasyonu. (FF, Chrome, IE11'de test edilmiştir)

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 () çağrıldığında işlev adını içeren bir dize uyarılır.

JS Fiddle Demosu: http://jsfiddle.net/mjgqfhbe/



1

Bilgiler 2016 yılında geçerlidir.


İşlev bildirimi sonuçları

Opera'da Sonuç

>>> (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

Chrome'da sonuç

(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

Düğümde Sonuç

> (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'ta çalışmıyor. IE ve Edge üzerinde test edilmedi.


İşlev ifadeleri için sonuçlar

Düğümde Sonuç

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

Chrome'da sonuç

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

Firefox, Opera'da çalışmıyor. IE ve Edge üzerinde test edilmedi.

Notlar:

  1. Anonim işlev kontrol etmek mantıklı değildir.
  2. Test ortamı

~ $ 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
})();

Yazı tipi varyasyonu:

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

f2(f1);  //Logs f1

Yalnızca ES6 / ES2015 uyumlu motorlarda mevcuttur. Daha fazla bilgi için


0

İşte bir astar:

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

Bunun gibi:

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

0

Bu Igor Ostroumov'un cevabının bir çeşidi :

Bir parametre için varsayılan değer olarak kullanmak isterseniz, 'arayan' için ikinci düzey bir çağrı düşünmeniz gerekir:

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

Bu, dinamik olarak birden fazla işlevde yeniden kullanılabilir bir uygulamaya izin verecektir.

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

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

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

function crow()
{
  bar();
}

foo();
crow();

Dosya adını da istiyorsanız, başka bir soruda F-3000'in cevabını kullanan bu çözüm :

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

Cevap kısa: alert(arguments.callee.name);


12
"nom", Fransızcada "isim" dir. Bu tür ayrıntılar tarayıcıların dil sürümleri arasında değişiyor mu? Ben öyle düşünmezdim.
argyle
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.