Respostas:
No ES5 e acima, não há acesso a essas informações.
Nas versões mais antigas do JS, você pode obtê-lo usando arguments.callee
.
Talvez você precise analisar o nome, pois provavelmente incluirá algum lixo extra. Porém, em algumas implementações, você pode simplesmente obter o nome usando arguments.callee.name
.
Análise:
function DisplayMyName()
{
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
}
arguments.callee
não é permitido no modo estrito.
Para funções não anônimas
function foo()
{
alert(arguments.callee.name)
}
Mas no caso de um manipulador de erros, o resultado seria o nome da função do manipulador de erros, não?
Tudo o que você precisa é simples. Criar função:
function getFuncName() {
return getFuncName.caller.name
}
Depois disso, sempre que precisar, basta usar:
function foo() {
console.log(getFuncName())
}
foo()
// Logs: "foo"
function getFuncName() { return getFuncName.name }
getFuncName
chamador e não o nome do chamador.
De acordo com a MDN
Aviso: A 5ª edição do ECMAScript (ES5) proíbe o uso de argument.callee () no modo estrito. Evite usar argument.callee (), dando um nome às expressões de função ou use uma declaração de função em que uma função deve se chamar.
Conforme observado, isso se aplica apenas se o seu script usar "modo estrito". Isso ocorre principalmente por razões de segurança e, infelizmente, atualmente não há alternativa para isso.
Isso deve servir:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
Para o chamador, basta usar caller.toString()
.
[
Isso deve estar na categoria de "hacks mais feios do mundo", mas aqui está.
Primeiro, imprimir o nome da função atual (como nas outras respostas) parece ter uso limitado para mim, já que você já sabe qual é a função!
No entanto, descobrir o nome da função de chamada pode ser bastante útil para uma função de rastreamento. Isso é com um regexp, mas usar indexOf seria cerca de 3x mais rápido:
function getFunctionName() {
var re = /function (.*?)\(/
var s = getFunctionName.caller.toString();
var m = re.exec( s )
return m[1];
}
function me() {
console.log( getFunctionName() );
}
me();
Aqui está uma maneira que funcionará:
export function getFunctionCallerName (){
// gets the text between whitespace for second part of stacktrace
return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
Então nos seus testes:
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);
});
});
Observe que o terceiro teste só funcionará se o teste estiver localizado em / util / functions
A getMyName
função no trecho abaixo retorna o nome da função de chamada. É um hack e depende de não-padrão recurso: Error.prototype.stack
. Observe que o formato da string retornada por Error.prototype.stack
é implementado de maneira diferente em diferentes mecanismos, portanto, isso provavelmente não funcionará em qualquer lugar:
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())
Sobre outras soluções: arguments.callee
não é permitido no modo estrito e nãoFunction.prototype.caller
é padrão e não é permitido no modo estrito .
Outro caso de uso pode ser um distribuidor de eventos vinculado no tempo de execução:
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);
A vantagem aqui é que o despachante pode ser facilmente reutilizado e não precisa receber a fila de despacho como argumento. Em vez disso, é implícito com o nome da chamada ...
No final, o caso geral apresentado aqui seria "usar o nome da função como argumento para que você não precise transmiti-lo explicitamente", e isso pode ser útil em muitos casos, como o retorno de chamada opcional jquery animate (), ou em retornos de chamada de intervalos / intervalos (ou seja, você passa apenas uma função NAME).
O nome da função atual e como ela pode ser obtida parece ter mudado nos últimos 10 anos, desde que essa pergunta foi feita.
Agora, não sendo um desenvolvedor profissional da Web que conhece todas as histórias de todos os navegadores que já existiram, eis como funciona para mim em um navegador Chrome de 2019:
function callerName() {
return callerName.caller.name;
}
function foo() {
let myname = callerName();
// do something with it...
}
Algumas das outras respostas encontraram alguns erros de cromo sobre código estrito de javascript e outros enfeites.
Desde que você escreveu uma função nomeada foo
e sabe que está nela, myfile.js
por que você precisa obter essas informações dinamicamente?
Dito isto, você pode usar arguments.callee.toString()
dentro da função (esta é uma representação de string de toda a função) e regexar o valor do nome da função.
Aqui está uma função que cuspirá seu próprio nome:
function foo() {
re = /^function\s+([^(]+)/
alert(re.exec(arguments.callee.toString())[1]);
}
Uma combinação das poucas respostas que eu vi aqui. (Testado em 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);
}
Chamar randomFunction () alertará uma string que contém o nome da função.
Demonstração JS Fiddle: http://jsfiddle.net/mjgqfhbe/
Uma resposta atualizada para isso pode ser encontrada nesta resposta: https://stackoverflow.com/a/2161470/632495
e, se você não quiser clicar:
function test() {
var z = arguments.callee.name;
console.log(z);
}
As informações são atuais no ano de 2016.
Resultado na Ópera
>>> (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
Resultado no 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
Resultado no 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
Não funciona no Firefox. Não testado no IE e no Edge.
Resultado no NodeJS
> var func11 = function(){
... console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11
Resultado no Chrome
var func11 = function(){
console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11
Não funciona no Firefox, Opera. Não testado no IE e no Edge.
Notas:
~ $ 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
})();
Variação tipográfica:
function f1() {}
function f2(f:Function) {
console.log(f.name);
}
f2(f1); //Logs f1
Nota disponível apenas em mecanismos compatíveis com ES6 / ES2015. Para mais, veja
Aqui está um liner:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')
Como isso:
function logChanges() {
let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
console.log(whoami + ': just getting started.');
}
Essa é uma variante da resposta de Igor Ostroumov :
Se você deseja usá-lo como um valor padrão para um parâmetro, considere uma chamada de segundo nível para 'chamador':
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
Isso permitiria dinamicamente uma implementação reutilizável em várias funções.
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 você quiser o nome do arquivo também, aqui está essa solução usando a resposta do F-3000 em outra pergunta:
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();
}
Experimentar:
alert(arguments.callee.toString());
A resposta é curta: alert(arguments.callee.name);