Могу ли я получить имя текущей функции в JavaScript?
можно ли сделать так:
myfile.js:
function foo() {
alert(<my-function-name>);
// pops-up "foo"
// or even better: "myfile.js : foo"
}
У меня есть фреймворки Dojo и jQuery в моем стеке, поэтому, если любой из них упрощает работу, они доступны.
17 ответов:
вы должны быть в состоянии сделать это с помощью
arguments.callee.вы, возможно, придется разобрать имя, хотя, как это, вероятно, будет включать в себя некоторые дополнительные нежелательной. Хотя, в некоторых реализациях вы можете просто получить имя с помощью
arguments.callee.name.анализ:
function DisplayMyName() { var myName = arguments.callee.toString(); myName = myName.substr('function '.length); myName = myName.substr(0, myName.indexOf('(')); alert(myName); }источник: Javascript-получить текущее имя функции.
для неанонимных функций
function foo() { alert(arguments.callee.name) }но в случае обработчика ошибок результатом будет имя функции обработчика ошибок, не так ли?
Это должно сделать это:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/); alert(fn[1]);для вызывающего абонента, просто используйте
caller.toString().
по данным MDN
предупреждение: 5-е издание ECMAScript (ES5) запрещает использование аргументов.callee () в строгом режиме. Избегайте использования аргументов.вызываемый объект() либо присваивает выражениям функции имя, либо использует объявление функции, в котором функция должна вызывать себя.
Как уже отмечалось, это относится только если ваш скрипт использует "строгий режим". Это в основном по соображениям безопасности и, к сожалению, в настоящее время нет Альтернатива для этого.
Это должно идти в категории "самые уродливые хаки в мире", но здесь вы идете.
во-первых, печать имени настоящее функция (как и в других ответах), похоже, имеет ограниченное использование для меня, так как вы уже знаете, что такое функция!
однако, узнав имя вызов функция может быть очень полезной для функции трассировки. Это с регулярным выражением, но с помощью indexOf будет около 3x быстрее:
function getFunctionName() { var re = /function (.*?)\(/ var s = getFunctionName.caller.toString(); var m = re.exec( s ) return m[1]; } function me() { console.log( getFunctionName() ); } me();
все, что вам нужно, это просто. Создать функцию:
function getFuncName() { return getFuncName.caller.name }после этого всякий раз, когда вам нужно, вы просто используете:
function foo() { console.log(getFuncName()) } foo() // Logs: "foo"
вот как это будет работать:
export function getFunctionCallerName (){ // gets the text between whitespace for second part of stacktrace return (new Error()).stack.match(/at (\S+)/g)[1].slice(3); }тогда в ваших тестах:
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); }); });обратите внимание, что третий тест будет работать только в том случае, если тест находится в /util/functions
другим вариантом использования может быть диспетчер событий, связанный во время выполнения:
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);преимущество здесь заключается в том, что диспетчер может быть легко повторно использован и не должен получать очередь отправки в качестве аргумента, вместо этого он приходит неявно с именем вызова...
в конце концов, общий случай, представленный здесь, будет "использовать имя функции в качестве аргумента, поэтому вам не нужно передавать его явно", и это может быть полезно во многих случаях, таких как jQuery animate() необязательный обратный вызов, или в таймаутах / интервалах обратных вызовов, (т. е. вы только передаете имя функции).
The
getMyNameфункция в приведенном ниже фрагменте возвращает имя вызывающей функции. Это хак и полагается на нестандартное характеристика:Error.prototype.stack.function getMyName() { var e = new Error('dummy'); var stack = e.stack .split('\n')[2] // " at functionName ( ..." => "functionName" .replace(/^\s+at\s+(.+?)\s.+/g, '' ); return stack } function foo(){ return getMyName() } function bar() { return foo() } console.log(bar())о других решениях:
arguments.calleeне работает в строгом режиме иFunction.prototype.callerэто нестандартное, но имеет лучшую поддержку, чемError.prototype.stack.
так как вы написали функцию с именем
fooи вы знаете, что это вmyfile.jsзачем вам нужно получить эту информацию динамически?это, как говорится, вы можете использовать
arguments.callee.toString()внутри функции (это строковое представление всей функции) и регулярное выражение значения имени функции.вот функция, которая выплюнет свое собственное имя:
function foo() { re = /^function\s+([^(]+)/ alert(re.exec(arguments.callee.toString())[1]); }
обновленный ответ на этот вопрос можно найти в этом ответе: https://stackoverflow.com/a/2161470/632495
и, если вам не хочется нажимать:
function test() { var z = arguments.callee.name; console.log(z); }
сочетание нескольких ответов которые я видел здесь. (Протестировано в 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); }вызов randomFunction () вызовет предупреждение строки, содержащей имя функции.
JS Fiddle Demo:http://jsfiddle.net/mjgqfhbe/
вот один лайнер:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')такой:
function logChanges() { let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', ''); console.log(whoami + ': just getting started.'); }
информация актуальна на 2016 год.
результаты для объявления функции
результат в опере
>>> (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
(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результат в 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не работает в Firefox. Непроверенные на IE и краю.
результаты для выражений функций
результат в NodeJS
> var func11 = function(){ ... console.log('Function name:', arguments.callee.name) ... }; func11(); Function name: func11в результате Хром
var func11 = function(){ console.log('Function name:', arguments.callee.name) }; func11(); Function name: func11не работает в Firefox, Opera. Непроверенные на IE и краю.
Примечания:
- анонимная функция не имеет смысла проверять.
- тестирование среды
~ $ 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 })();вариант машинописного текста:
function f1() {} function f2(f:Function) { console.log(f.name); } f2(f1); //Logs f1Примечание доступно только в ES6 / ES2015 совместимых двигателях. подробнее
Comments