Est-il possible de faire cela:
myfile.js:
function foo() {
alert(<my-function-name>);
// pops-up "foo"
// or even better: "myfile.js : foo"
}
J'ai les frameworks Dojo et jQuery dans ma pile, donc si cela facilite les choses, ils sont disponibles.
Vous devriez pouvoir l'obtenir en utilisant arguments.callee
.
Cependant, vous devrez peut-être analyser le nom, car il comprendra probablement des fichiers indésirables. Cependant, dans certaines implémentations, vous pouvez simplement obtenir le nom en utilisant arguments.callee.name
.
Analyse:
function DisplayMyName()
{
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
}
Source: Javascript - Obtenir le nom de la fonction actuelle .
Pour les fonctions non anonymes
function foo()
{
alert(arguments.callee.name)
}
Mais en cas de gestionnaire d'erreur, le résultat serait le nom de la fonction de gestionnaire d'erreur, n'est-ce pas?
Selon MDN
Attention: La 5ème édition de ECMAScript (ES5) interdit l'utilisation de arguments.callee () en mode strict. Évitez d'utiliser arguments.callee () en attribuant un nom aux expressions de fonction ou en utilisant une déclaration de fonction dans laquelle une fonction doit s'appeler elle-même.
Comme indiqué précédemment, cela ne s'applique que seulement si votre script utilise le "mode strict". C’est principalement pour des raisons de sécurité et, malheureusement, il n’existe actuellement aucune alternative.
Tout ce dont vous avez besoin est simple… .. Créer une fonction:
function getFuncName() {
return getFuncName.caller.name
}
Après cela chaque fois que vous avez besoin, vous utilisez simplement:
function foo() {
console.log(getFuncName())
}
foo()
// Logs: "foo"
Cela devrait le faire:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
Pour l'appelant, utilisez simplement caller.toString()
.
Cela doit entrer dans la catégorie des "hack les plus laids du monde", mais c'est parti.
Tout d’abord, imprimer le nom de la fonction current (comme dans les autres réponses) semble avoir une utilité limitée pour moi, car vous savez déjà en quelque sorte la fonction!
Cependant, connaître le nom de la fonction-appelant peut être très utile pour une fonction de trace. C'est avec une expression rationnelle, mais utiliser indexOf serait environ 3 fois plus rapide:
function getFunctionName() {
var re = /function (.*?)\(/
var s = getFunctionName.caller.toString();
var m = re.exec( s )
return m[1];
}
function me() {
console.log( getFunctionName() );
}
me();
Voici une façon qui fonctionnera:
export function getFunctionCallerName (){
// gets the text between whitespace for second part of stacktrace
return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
Puis dans vos tests:
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);
});
});
Notez que le troisième test ne fonctionnera que si le test est situé dans/util/functions
Un autre cas d'utilisation pourrait être un répartiteur d'événements lié au moment de l'exécution:
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);
L'avantage ici est que le répartiteur peut être facilement réutilisé et qu'il n'est pas nécessaire de recevoir la file d'attente de distribution en tant qu'argument, mais qu'il est implicite avec le nom d'invocation ...
En fin de compte, le cas général présenté ici serait "d'utiliser le nom de la fonction en tant qu'argument pour éviter de le passer explicitement", ce qui peut être utile dans de nombreux cas, tels que le rappel facultatif jquery animate (), ou dans des rappels de timeouts/intervalles (c’est-à-dire que vous ne transmettez qu’un nom de fonction).
La fonction getMyName
de l'extrait ci-dessous renvoie le nom de la fonction appelante. C'est un hack et repose sur non standard feature: Error.prototype.stack
. Notez que le format de la chaîne renvoyée par Error.prototype.stack
est implémenté différemment dans différents moteurs, donc cela ne fonctionnera probablement pas partout:
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())
À propos des autres solutions: arguments.callee
n'est pas autorisé en mode strict et Function.prototype.caller
is n'est pas standard et n'est pas autorisé en mode strict .
Puisque vous avez écrit une fonction nommée foo
et que vous savez qu'elle est dans myfile.js
, pourquoi devez-vous obtenir cette information de manière dynamique?
Cela étant dit, vous pouvez utiliser arguments.callee.toString()
dans la fonction (il s’agit d’une représentation sous forme de chaîne de la fonction entière) et regex la valeur du nom de la fonction.
Voici une fonction qui va cracher son propre nom:
function foo() {
re = /^function\s+([^(]+)/
alert(re.exec(arguments.callee.toString())[1]);
}
Vous trouverez une réponse à jour à cette réponse à l'adresse suivante: https://stackoverflow.com/a/2161470/632495
et, si vous n'avez pas envie de cliquer:
function test() {
var z = arguments.callee.name;
console.log(z);
}
Une combinaison des quelques réponses que j'ai vues ici. (Testé en 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);
}
L'appel de randomFunction () alertera une chaîne contenant le nom de la fonction.
Démo de JS Fiddle: http://jsfiddle.net/mjgqfhbe/
(function f() {
console.log(f.name); //logs f
})();
Variation TypeScript:
function f1() {}
function f2(f:Function) {
console.log(f.name);
}
f2(f1); //Logs f1
Remarque disponible uniquement dans les moteurs conformes ES6/ES2015. Pour plus voir
Les informations sont réelles sur l'année 2016.
Résultat à l'Opéra
>>> (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
Résultat dans le 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
Résultat dans le 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
Ne fonctionne pas dans Firefox. Non testé sur IE et Edge.
Résultat dans le NodeJS
> var func11 = function(){
... console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11
Résultat dans le Chrome
var func11 = function(){
console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11
Ne fonctionne pas dans Firefox, Opera. Non testé sur IE et Edge.
Remarques:
~ $ 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
C'est une variante de d'Igor Ostroumov réponse:
Si vous souhaitez l'utiliser comme valeur par défaut pour un paramètre, vous devez envisager un appel de second niveau à 'caller':
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
Cela permettrait dynamiquement une implémentation réutilisable dans plusieurs fonctions.
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{
alert(myFunctionName);
}
// pops-up "foo"
function foo()
{
bar();
}
function crow()
{
bar();
}
foo();
crow();
Si vous voulez aussi le nom du fichier, voici cette solution en utilisant la réponse de F-3000 sur une autre question:
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();
}
Voici un one liner:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')
Comme ça:
function logChanges() {
let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
console.log(whoami + ': just getting started.');
}