Как получить имя функции из этой функции?
Как получить доступ к имени функции из этой функции?
// parasitic inheritance
var ns.parent.child = function() {
var parent = new ns.parent();
parent.newFunc = function() {
}
return parent;
}
var ns.parent = function() {
// at this point, i want to know who the child is that called the parent
// ie
}
var obj = new ns.parent.child();
Ответы
Ответ 1
В ES5 лучше всего сделать следующее:
function functionName(fun) {
var ret = fun.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}
Использование Function.caller
является нестандартным. Function.caller
и arguments.callee
запрещены в строгом режиме.
Изменить: ответ на основе nus regex ниже обеспечивает одно и то же, но имеет лучшую производительность!
В ES6 вы можете просто использовать myFunction.name
.
Примечание. Остерегайтесь того, что некоторые JS minifiers могут выкидывать имена функций, улучшать сжатие; вам может потребоваться изменить настройки, чтобы избежать этого.
Ответ 2
ES6 (вдохновлен ответом sendy halim ниже):
myFunction.name
Объяснение в MDN. С 2015 года работает в nodejs и во всех основных браузерах, кроме IE.
Примечание. В связанных функциях это даст "bound <originalName>
". Вам нужно будет снять "привязку", если вы хотите получить оригинальное имя.
ES5 (вдохновленный ответом Влада):
Если у вас есть ссылка на функцию, вы можете сделать:
function functionName( func )
{
// Match:
// - ^ the beginning of the string
// - function the word 'function'
// - \s+ at least some white space
// - ([\w\$]+) capture one or more valid JavaScript identifier characters
// - \s* optionally followed by white space (in theory there won't be any here,
// so if performance is an issue this can be omitted[1]
// - \( followed by an opening brace
//
var result = /^function\s+([\w\$]+)\s*\(/.exec( func.toString() )
return result ? result[ 1 ] : '' // for an anonymous function there won't be a match
}
- Я не запускал модульные тесты на этом или проверенную реализацию
различия, но в принципе он должен работать, если не оставить комментарий.
- Примечание: не будет работать над связанными функциями
- Примечание:
caller
и callee
считаются устаревшими.
[1] Я включаю его здесь, потому что он легален и часто достаточно синтаксиса, чтобы не учитывать пробел между именем функции и скобками. С другой стороны, я не знаю о какой-либо реализации .toString(), которая будет включать в себя пробел здесь, поэтому вы можете ее опустить.
Как ответ на исходный вопрос, я бы отказался от паразитического наследования и пошел на некоторые более традиционные шаблоны проектирования ООП. Я написал TidBits.OoJs, чтобы удобно писать код OOP в JavaScript с набором функций, имитирующим С++ (еще не полный, но в основном).
Я вижу из комментариев, что вы хотели бы избежать передачи информации parent
ему нужно конструктор. Я должен признать, что традиционные шаблоны дизайна не избавят вас от этого, хотя, как правило, считается хорошей задачей сделать ваши зависимости очевидными и принудительными.
Я бы также предложил уклониться от анонимных функций. Они делают только отладку и профилирование PITA, потому что все просто отображается как "анонимная функция", и я не знаю о них.
Ответ 3
то, что вы делаете, это назначение неназначенной функции переменной. вам, вероятно, понадобится выражение с именованной функцией (http://kangax.github.com/nfe/).
var x = function x() {
console.log( arguments.callee.name );
}
x();
однако я не уверен, сколько кросс-браузера это; есть проблема с IE6, которая делает вас утечкой имени функции во внешнюю область. Кроме того, arguments.callee является устаревшим и приведет к ошибке, если вы используете strict mode
.
Ответ 4
Любой constructor
предоставляет свойство name
, которое является именем функции. Вы получаете доступ к constructor
через экземпляр (используя new
) или prototype
:
function Person() {
console.log(this.constructor.name); //Person
}
var p = new Person();
console.log(p.constructor.name); //Person
console.log(Person.prototype.constructor.name); //Person
Ответ 5
Это может сработать для вас:
function foo() { bar(); }
function bar() { console.log(bar.caller.name); }
running foo() выведет "foo" или undefined, если вы вызываете анонимную функцию.
Он также работает с конструкторами, и в этом случае он выводит имя вызывающего конструктора (например, "Foo" ).
Дополнительная информация здесь: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller
Они утверждают, что они нестандартные, но также и поддерживаются всеми основными браузерами: Firefox, Safari, Chrome, Opera и IE.
Ответ 6
Похоже, самая глупая вещь, которую я написал в своей жизни, но это смешно: D
function getName(d){
const error = new Error();
const firefoxMatch = (error.stack.split('\n')[0 + d].match(/^.*([email protected])/) || [])[0];
const chromeMatch = ((((error.stack.split('at ') || [])[1 + d] || '').match(/(^|\.| <| )(.*[^(<])( \()/) || [])[2] || '').split('.').pop();
const safariMatch = error.stack.split('\n')[0 + d];
// firefoxMatch ? console.log('firefoxMatch', firefoxMatch) : void 0;
// chromeMatch ? console.log('chromeMatch', chromeMatch) : void 0;
// safariMatch ? console.log('safariMatch', safariMatch) : void 0;
return firefoxMatch || chromeMatch || safariMatch;
}
d
- глубина стека. 0
- вернуть имя этой функции, 1
- родительский и т. Д.;
[0 + d]
- просто для понимания - что происходит;
firefoxMatch
- работает для сафари, но у меня было очень мало времени на тестирование, потому что владелец Mac вернулся после курения и отогнал меня: '(
Тестирование:
function limbo(){
for(let i = 0; i < 4; i++){
console.log(getName(i));
}
}
function lust(){
limbo();
}
function gluttony(){
lust();
}
gluttony();
Результат:
Хром:
![enter image description here]()
Fitefox:
![enter image description here]()
Это решение создавалось только для удовольствия! Не используйте его для реальных проектов. Это не зависит от спецификации ES, это зависит только от реализации браузера. После следующего обновления chrome/firefox/safari оно может быть повреждено.
Более того, при обработке ошибок (ха) не будет - если d
будет больше длины стека - вы получите ошибку;
Для других шаблонов сообщений об ошибках - вы получите сообщение об ошибке;
Он должен работать для классов ES6 (.split('.').pop()
), но вы все равно можете получить erorr;
Ответ 7
Вы не можете. Функции не имеют имен в соответствии со стандартом (хотя у mozilla есть такой атрибут) - они могут быть назначены только переменным с именами.
Также ваш комментарий:
// access fully qualified name (ie "my.namespace.myFunc")
находится внутри функции my.namespace.myFunc.getFn
Что вы можете сделать, это вернуть конструктор объекта, созданного с помощью нового
Итак, вы могли бы сказать
var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc
Ответ 8
Вы можете использовать свойство name
для получения имени функции, если вы не используете анонимную функцию
Например:
var Person = function Person () {
this.someMethod = function () {};
};
Person.prototype.getSomeMethodName = function () {
return this.someMethod.name;
};
var p = new Person();
// will return "", because someMethod is assigned with anonymous function
console.log(p.getSomeMethodName());
теперь попробуйте с именованной функцией
var Person = function Person () {
this.someMethod = function someMethod() {};
};
теперь вы можете использовать
// will return "someMethod"
p.getSomeMethodName()
Ответ 9
Вы можете использовать имя конструктора как:
{your_function}.prototype.constructor.name
этот код просто возвращает имя метода.
Ответ 10
Вы можете использовать Function.name
:
В большинстве реализаций JavaScript, когда у вас есть ссылка на конструктор в области видимости, вы можете получить его имя строки из своего свойства имени (например, имя_функции или Object.constructor.name
Вы можете использовать Function.callee
:
Нативный метод arguments.caller
устарел, но большинство браузеров поддерживают Function.caller
, который вернет фактический вызывающий объект (его тело кода):
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fcaller
Вы можете создать исходную карту:
Если вам нужна буквальная сигнатура функции ( "имя" ), а не сам объект, вам, возможно, придется прибегнуть к чему-то более настраиваемому, например, создать ссылку на массив значений строки API, Вам нужно будет часто обращаться. Вы можете сопоставлять их вместе с помощью Object.keys()
и вашего массива строк или просматривать библиотеку исходных карт Mozilla в GitHub для больших проектов:
https://github.com/mozilla/source-map
Ответ 11
Вы можете использовать это для браузеров, которые поддерживают Error.stack (возможно, не почти все)
function WriteSomeShitOut(){
var a = new Error().stack.match(/at (.*?) /);
console.log(a[1]);
}
WriteSomeShitOut();
конечно, это для текущей функции, но вы поняли.
счастливый пускать слюни, пока вы код
Ответ 12
как часть ECMAScript 6
вы можете использовать Function.name method
function doSomething() {}
alert(doSomething.name); // alerts "doSomething"
Ответ 13
Я знаю, что это старый вопрос, но в последнее время я сталкивался с подобной проблемой, пытаясь украсить некоторые методы React Component для целей отладки. Как уже говорили люди, arguments.caller
и arguments.callee
запрещены в строгом режиме, который, вероятно, включен по умолчанию в вашем переводе React. Вы можете либо отключить его, либо я смог придумать еще один хак, потому что в React все функции класса названы, вы можете это сделать:
Component.prototype.componentWillMount = function componentWillMount() {
console.log('Callee name: ', this.__proto__.constructor.toString().substr(0,30));
...
}
Ответ 14
У меня была аналогичная проблема, и я решил ее следующим образом:
Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace( "function ", "" );
}
Этот код более удобным образом реализует один ответ, который я уже читал здесь в начале этой дискуссии.
Теперь у меня есть функция-член, получающая имя любого объекта функции.
Здесь полный script...
<script language="javascript" TYPE="text/javascript">
Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace("function ", "" );
}
function call_this( _fn ) { document.write( _fn.myname() ); }
function _yeaaahhh() { /* do something */ }
call_this( _yeaaahhh );
</script>
Ответ 15
Это сработало для меня.
function AbstractDomainClass() {
this.className = function() {
if (!this.$className) {
var className = this.constructor.toString();
className = className.substr('function '.length);
className = className.substr(0, className.indexOf('('));
this.$className = className;
}
return this.$className;
}
}
Тестовый код:
var obj = new AbstractDomainClass();
expect(obj.className()).toBe('AbstractDomainClass');
Ответ 16
Если я понял, что вы хотите сделать, это то, что я делаю внутри конструктора функции.
if (!(this instanceof arguments.callee)) {
throw "ReferenceError: " + arguments.callee.name + " is not defined";
}
Ответ 17
Это будет работать в ES5, ES6, во всех браузерах и в строгом режиме.
Вот как это выглядит с именованной функцией.
(function myName() {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at myName (<anonymous>:2:15)
Вот как это выглядит с анонимной функцией.
(() => {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at <anonymous>:2:15
Ответ 18
смотрите здесь: http://www.tek-tips.com/viewthread.cfm?qid=1209619
arguments.callee.toString();
кажется правильным для ваших нужд.
Ответ 19
вы можете использовать Error.stack для отслеживания имени функции и точной позиции, в которой вы находитесь.
См. stacktrace.js
Ответ 20
Легкий способ получить имя функции изнутри функции fuction.
function x(){alert(this.name)};x()