Risposte:
In ES5 e versioni successive, non è possibile accedere a tali informazioni.
Nelle versioni precedenti di JS puoi ottenerlo utilizzando arguments.callee
.
Tuttavia, potresti dover analizzare il nome, poiché probabilmente includerà un po 'di spazzatura. Tuttavia, in alcune implementazioni puoi semplicemente ottenere il nome usandoarguments.callee.name
.
Analisi:
function DisplayMyName()
{
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
}
Fonte: Javascript: ottieni il nome della funzione corrente .
arguments.callee
non è consentito in modalità rigorosa.
Per funzioni non anonime
function foo()
{
alert(arguments.callee.name)
}
Ma nel caso di un gestore degli errori il risultato sarebbe il nome della funzione del gestore degli errori, no?
Tutto ciò di cui hai bisogno è semplice. Crea funzione:
function getFuncName() {
return getFuncName.caller.name
}
Dopodiché ogni volta che ne hai bisogno, usi semplicemente:
function foo() {
console.log(getFuncName())
}
foo()
// Logs: "foo"
function getFuncName() { return getFuncName.name }
getFuncName
anziché il nome del suo chiamante.
Secondo MDN
Avvertenza: la quinta edizione di ECMAScript (ES5) vieta l'uso di argument.callee () in modalità rigorosa. Evita di usare argomenti.callee () dando un nome alle espressioni di funzione o usa una dichiarazione di funzione dove una funzione deve chiamarsi.
Come notato, questo vale solo se lo script utilizza la "modalità rigorosa". Ciò è principalmente per motivi di sicurezza e purtroppo attualmente non esiste alternativa per questo.
Questo dovrebbe farlo:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
Per il chiamante, basta usare caller.toString()
.
[
Questo deve rientrare nella categoria degli "hack più brutti del mondo", ma ecco qui.
Innanzitutto, stampando il nome della corrente funzione (come nelle altre risposte) mi sembra avere un uso limitato, dato che sai già qual è la funzione!
Tuttavia, scoprire il nome della funzione chiamante potrebbe essere molto utile per una funzione di traccia. Questo è con una regexp, ma l'uso di indexOf sarebbe circa 3 volte più veloce:
function getFunctionName() {
var re = /function (.*?)\(/
var s = getFunctionName.caller.toString();
var m = re.exec( s )
return m[1];
}
function me() {
console.log( getFunctionName() );
}
me();
Ecco un modo che funzionerà:
export function getFunctionCallerName (){
// gets the text between whitespace for second part of stacktrace
return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
Quindi nei tuoi test:
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);
});
});
Si noti che il terzo test funzionerà solo se il test si trova in / util / funzioni
La getMyName
funzione nello snippet seguente restituisce il nome della funzione chiamante. Si tratta di un hack e si basa su non standard funzione: Error.prototype.stack
. Si noti che il formato della stringa restituito da Error.prototype.stack
viene implementato in modo diverso nei diversi motori, quindi probabilmente non funzionerà ovunque:
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())
Informazioni su altre soluzioni: arguments.callee
non è consentito in modalità rigorosa e nonFunction.prototype.caller
è standard e non è consentito in modalità rigorosa .
Un altro caso d'uso potrebbe essere un dispatcher di eventi associato al runtime:
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);
Il vantaggio qui è che il dispatcher può essere facilmente riutilizzato e non deve ricevere la coda di invio come argomento, ma è implicito con il nome dell'invocazione ...
Alla fine, il caso generale presentato qui sarebbe "usare il nome della funzione come argomento in modo da non doverlo passare esplicitamente", e ciò potrebbe essere utile in molti casi, come il callback opzionale jquery animate (), o in timeout / intervalli richiamate, (ovvero si passa solo una funzione NAME).
Il nome della funzione corrente e come può essere ottenuto sembra essere cambiato negli ultimi 10 anni, da quando è stata posta questa domanda.
Ora, non essendo uno sviluppatore web professionista che conosce tutte le storie di tutti i browser che siano mai esistiti, ecco come funziona per me in un browser Chrome 2019:
function callerName() {
return callerName.caller.name;
}
function foo() {
let myname = callerName();
// do something with it...
}
Alcune delle altre risposte si sono imbattute in alcuni errori di Chrome sul codice javascript rigoroso e quant'altro.
Dal momento che hai scritto una funzione denominata foo
e sai che è myfile.js
perché hai bisogno di ottenere queste informazioni in modo dinamico?
Detto questo, è possibile utilizzare arguments.callee.toString()
all'interno della funzione (questa è una rappresentazione in forma di stringa dell'intera funzione) e ripetere il valore del nome della funzione.
Ecco una funzione che sputerà il suo nome:
function foo() {
re = /^function\s+([^(]+)/
alert(re.exec(arguments.callee.toString())[1]);
}
Una combinazione delle poche risposte che ho visto qui. (Testato in 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);
}
La chiamata di randomFunction () avviserà una stringa che contiene il nome della funzione.
Demo JS Fiddle: http://jsfiddle.net/mjgqfhbe/
Una risposta aggiornata a questa può essere trovata su questa risposta: https://stackoverflow.com/a/2161470/632495
e, se non ti va di fare clic:
function test() {
var z = arguments.callee.name;
console.log(z);
}
Le informazioni sono aggiornate al 2016 anno.
Risultato nell'opera
>>> (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
Risultato in Chrome
(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
Risultato in 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
Non funziona in Firefox. Non testato su IE e Edge.
Risultato in NodeJS
> var func11 = function(){
... console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11
Risultato in Chrome
var func11 = function(){
console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11
Non funziona in Firefox, Opera. Non testato su IE e Edge.
Appunti:
~ $ 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
(function f() {
console.log(f.name); //logs f
})();
Variazione dattiloscritta:
function f1() {}
function f2(f:Function) {
console.log(f.name);
}
f2(f1); //Logs f1
Nota disponibile solo nei motori conformi a ES6 / ES2015. Per di più vedi
Ecco una fodera:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')
Come questo:
function logChanges() {
let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
console.log(whoami + ': just getting started.');
}
Questa è una variante di Igor Ostroumov risposta :
Se si desidera utilizzarlo come valore predefinito per un parametro, è necessario considerare una chiamata di secondo livello a "chiamante":
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
Ciò consentirebbe dinamicamente un'implementazione riutilizzabile in più funzioni.
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{
alert(myFunctionName);
}
// pops-up "foo"
function foo()
{
bar();
}
function crow()
{
bar();
}
foo();
crow();
Se vuoi anche il nome del file, ecco quella soluzione usando la risposta di F-3000 su un'altra domanda:
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();
}
Provare:
alert(arguments.callee.toString());