Odpowiedzi:
W ES5 i nowszych nie ma dostępu do tych informacji.
W starszych wersjach JS można go uzyskać za pomocą arguments.callee
.
Być może będziesz musiał przeanalizować nazwę, ponieważ prawdopodobnie będzie zawierać dodatkowe śmieci. Chociaż w niektórych implementacjach możesz po prostu uzyskać nazwę za pomocą arguments.callee.name
.
Rozbiór gramatyczny zdania:
function DisplayMyName()
{
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
}
arguments.callee
nie jest dozwolone w trybie ścisłym.
Dla funkcji nieanonimowych
function foo()
{
alert(arguments.callee.name)
}
Ale w przypadku procedury obsługi błędów wynikiem będzie nazwa funkcji obsługi błędów, prawda?
Wszystko, czego potrzebujesz, jest proste. Utwórz funkcję:
function getFuncName() {
return getFuncName.caller.name
}
Następnie, gdy tylko potrzebujesz, po prostu użyj:
function foo() {
console.log(getFuncName())
}
foo()
// Logs: "foo"
function getFuncName() { return getFuncName.name }
getFuncName
zamiast nazwy osoby dzwoniącej.
Według MDN
Ostrzeżenie: 5. wydanie ECMAScript (ES5) zabrania używania arguments.callee () w trybie ścisłym. Unikaj używania arguments.callee (), nadając wyrażeniom funkcji nazwę, lub użyj deklaracji funkcji, w której funkcja musi się wywoływać.
Jak wspomniano, dotyczy to tylko sytuacji, gdy skrypt używa „trybu ścisłego”. Wynika to głównie ze względów bezpieczeństwa i niestety obecnie nie ma na to alternatywy.
To powinno to zrobić:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
Dla dzwoniącego wystarczy użyć caller.toString()
.
[
To musi należeć do kategorii „najbrzydszych hacków na świecie”, ale proszę bardzo.
Po pierwsze, wydrukowanie nazwy bieżącej funkcji (jak w innych odpowiedziach) wydaje się mieć dla mnie ograniczone zastosowanie, ponieważ już wiesz, co to jest funkcja!
Jednak znalezienie nazwy funkcji wywołującej może być bardzo przydatne dla funkcji śledzenia. Jest to z wyrażeniem regularnym, ale użycie indexOf byłoby około 3 razy szybsze:
function getFunctionName() {
var re = /function (.*?)\(/
var s = getFunctionName.caller.toString();
var m = re.exec( s )
return m[1];
}
function me() {
console.log( getFunctionName() );
}
me();
Oto sposób, który zadziała:
export function getFunctionCallerName (){
// gets the text between whitespace for second part of stacktrace
return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
Następnie w twoich testach:
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);
});
});
Zauważ, że trzeci test będzie działał tylko wtedy, gdy będzie on zlokalizowany w / util / functions
getMyName
Funkcja we fragmencie poniżej zwraca nazwę funkcji wywołującej. Jest to hack i opiera się na niestandardowym funkcji: Error.prototype.stack
. Zwróć uwagę, że format zwracanego ciągu Error.prototype.stack
jest różnie zaimplementowany w różnych silnikach, więc prawdopodobnie nie będzie to działać wszędzie:
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())
O innych rozwiązaniach: arguments.callee
nie jest dozwolone w trybie ścisłym i Function.prototype.caller
jest niestandardowe i niedozwolone w trybie ścisłym .
Innym przypadkiem użycia może być dyspozytor zdarzeń związany w czasie wykonywania:
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);
Zaletą jest to, że dyspozytor może być łatwo ponownie użyty i nie musi odbierać kolejki wysyłki jako argumentu, zamiast tego jest implikowany z nazwą wywołania ...
W końcu ogólny przypadek przedstawiony tutaj to „użycie nazwy funkcji jako argumentu, abyś nie musiał przekazywać jej jawnie”, a to może być przydatne w wielu przypadkach, takich jak opcjonalne wywołanie zwrotne jquery animate (), lub w wywołaniach zwrotnych limitów czasu / interwałów (tzn. przekazujesz tylko NAZWĘ funcion).
Nazwa obecnej funkcji i sposób jej uzyskania wydaje się zmieniać w ciągu ostatnich 10 lat, odkąd zadano to pytanie.
Teraz, nie będąc profesjonalnym programistą, który zna wszystkie historie wszystkich przeglądarek, jakie kiedykolwiek istniały, oto jak to działa dla mnie w przeglądarce Chrome 2019:
function callerName() {
return callerName.caller.name;
}
function foo() {
let myname = callerName();
// do something with it...
}
W niektórych innych odpowiedziach wystąpiły błędy Chrome dotyczące ścisłego kodu javascript i nie tylko.
Ponieważ napisałeś funkcję o nazwie foo
i wiesz, myfile.js
dlaczego właśnie dlatego potrzebujesz dynamicznie uzyskiwać te informacje?
Biorąc to pod uwagę, możesz użyć arguments.callee.toString()
wewnątrz funkcji (jest to ciąg znaków reprezentujący całą funkcję) i ponownie wyrejestrować wartość nazwy funkcji.
Oto funkcja, która wypluje swoją nazwę:
function foo() {
re = /^function\s+([^(]+)/
alert(re.exec(arguments.callee.toString())[1]);
}
Kombinacja kilku odpowiedzi, które tu widziałem. (Testowane w 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);
}
Wywołanie randomFunction () zaalarmuje ciąg zawierający nazwę funkcji.
JS Fiddle Demo: http://jsfiddle.net/mjgqfhbe/
Zaktualizowaną odpowiedź na to można znaleźć pod następującą odpowiedzią: https://stackoverflow.com/a/2161470/632495
a jeśli nie masz ochoty klikać:
function test() {
var z = arguments.callee.name;
console.log(z);
}
Informacje są aktualne w 2016 roku.
Wynik w Operze
>>> (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
Wynik w 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
Wynik w 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
Nie działa w przeglądarce Firefox. Nie przetestowano w IE i Edge.
Wynik w NodeJS
> var func11 = function(){
... console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11
Wynik w Chrome
var func11 = function(){
console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11
Nie działa w przeglądarce Firefox, Opera. Nie przetestowano w IE i Edge.
Uwagi:
~ $ 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
})();
Odmiana maszynopisu:
function f1() {}
function f2(f:Function) {
console.log(f.name);
}
f2(f1); //Logs f1
Uwaga dostępna tylko w silnikach zgodnych z ES6 / ES2015. Więcej patrz
Oto jeden liniowiec:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')
Lubię to:
function logChanges() {
let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
console.log(whoami + ': just getting started.');
}
To wariant odpowiedzi Igora Ostroumova :
Jeśli chcesz użyć go jako wartości domyślnej parametru, musisz rozważyć wywołanie drugiego poziomu do „dzwoniącego”:
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
Umożliwiłoby to dynamicznie implementację wielokrotnego użytku w wielu funkcjach.
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{
alert(myFunctionName);
}
// pops-up "foo"
function foo()
{
bar();
}
function crow()
{
bar();
}
foo();
crow();
Jeśli chcesz również nazwę pliku, oto rozwiązanie wykorzystujące odpowiedź F-3000 na inne pytanie:
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();
}