Получить имя функции, подобное напечатанному в консоли Chrome
Учитывая этот код:
var o = {};
o.f = function(){};
new o.f;
Хромовые принты o.f {}
в консоль. Ты знаешь как это o.f
часть называется? Что еще более важно, есть ли способ получить этот результат без использования консоли? Я хотел бы извлечь имя метода из самой функции, то есть без какой-либо дополнительной информации.
Я уже знаю, как получить имя в этом случае:
function f(){}
f+'' // "function f(){}"
Но это не ведет себя так же, как в ситуации, описанной выше.
Следующее содержание в основном скопировано из комментариев.
Я хотел знать, есть ли "техническое" слово, чтобы поговорить об этом o.f
шаблон, скажем, например, "пространство имен", "идентификатор" или "путь к функции". Затем мне стало интересно, есть ли способ извлечь эту информацию из загруженного скрипта на веб-странице. Следующий вопрос может помочь вам понять мою цель, абзац, который находится сразу после первого блока кода, очень близок моей идее: сохраняет ли Chrome конструктор каждого объекта?,
Возможно, я должен был упомянуть, что моей первоначальной целью было создание документации во время выполнения: / В этом случае было бы полезно что-то вроде API отражения. Точнее, я искал способ включить имя метода в декомпилированную форму функции. Посмотрите:
function Class(){}
Class.prototype.method = function(){};
Class.prototype.method + ''
дает function(){}
, Я хотел бы ввести имя метода, чтобы получить этот результат: function method(){}
,
Проблема в том, что у меня нет никакой информации о том, какую функцию я в данный момент сериализирую, поскольку операция происходит, когда пользователь нажимает на ссылку. Я знаю, что мог бы легко хранить имя где-нибудь, например, привязывая данные к элементу привязки, для меня это очевидно, мне было просто интересно узнать, есть ли способ получить эти данные так же, как в Chrome.
3 ответа
Что ж, это кажется достаточно простым вопросом, поскольку наименование всех этих конструкций идет так:
o.f = function(){};
это общее утверждение, состоящее из еще более распространенных выражений. o.f
это просто один из двух способов доступа к свойствам объектов, обычно называемых точечной нотацией. Хотя я верю в JS, точка (.) На самом деле не рассматривается как оператор, и впредь я буду называть ее оператором-членом.
Далее у нас есть известный оператор присваивания, который назначает правый операнд слева (член объекта o
, называется f
).
Правое выражение (должно быть оценено как единичное значение) - это определение функции, которое вместо отдельного оператора используется в качестве выражения. Учитывая этот факт, мы называем это использование функций как выражения функций.
В данном конкретном случае у функции нет имени, это анонимная функция. Внутренне большинство - если не все двигатели - дадут ему имя, но это не то, что JS должен знать или действительно беспокоиться. Что касается JS, эта функция не имеет имени и доступна только через o.f
, Если вы вызываете эту функцию так: o.f()
его контекст будет контекстом объекта o
эффективно заставляя эту функцию вести себя как метод.
Таким образом, в основном ваше утверждение звучит так: "Назначьте и создайте, если необходимо, члену o
называется f
, анонимная функция." Сама функция не имеет имени.
Учти это:
var o = {f: function(){console.log('I am a function');}};
var foobar = o.f;
foobar();//logs I am a function
Так сказать название функции o.f
является f
не всегда применяется. Другие переменные или свойства могут ссылаться на ту же функцию. Это потому, что функции являются объектами первого класса, они могут быть возвращены, переданы и назначены, из чего угодно и чем угодно.
Ответ, таким образом, заключается в использовании любого из этих двух подходов:
Вы можете изменить выражение функции, добавив имя, чтобы превратить его в выражение с именованной функцией:
f.o = function newName(){};
newName
имя, кроме старых версий IE, недоступно за пределами области действия функций. Это требуется спецификациями ECMA, см. Подробности здесь. Во всяком случае, теперь мы можем проверить это:
var func = function func(){console.log(func);};
//same name:
func();//logs function func(){}
var foobar = func;
foobar();//logs function func(){}
func = 123;//<-- no longer function
foobar();//still function func(){}//func is still accessible
var hidden = (function()
{
return function named()
{
console.log(named);//access name
};
}());
hidden();//logs function named(){}
console.log(named);//undefined -> not visible outside the function itself
Имя функции ограничено ее собственной областью действия.
Используйте регулярное выражение, которое немного хакерское и не использует две переменные / свойства, ссылающиеся на один и тот же объект функции:
o = {f: function(){console.log('I am a function');}};
for (var pName in o)
{//probably add o.hasOwnProperty(pName) check to be safe
if (o[pName] instanceof Function)
{
console.log(o.f.toString().replace(
/^function\s*\(/,
'function o.'+pName+'(')
);
}
}
Это приводит в порядок функцию (давая function (){/*body*/}
) и заменяет function (
с function <propertyName>(
, Если у функции уже было собственное имя, это имя не заменяется.
В общем, это не распространенная практика в Javascript или в программировании в целом.
Тем не мение, function
У них есть имя атрибута - см. Function.name. но в вашем коде o.f
это безымянная функция.
var o = {};
o.f = function(){}; //function (){} creates a nameless function.
Вы можете определить имя до ()
var o = {};
o.f = function f(){}; //function f(){} creates a function with the name f
затем
o.f.name == 'f'
ПРИМЕЧАНИЕ: эта функциональность НЕ поддерживается в IE и не является спецификацией EMCA.
Это выставлено как name
свойство функции, и в наши дни она является частью стандарта (поиск SetFunctionName
в спецификации). См. Также MDN, Chrome Platform Status, поддержка браузера. Если вы спрашиваете конкретно о функции автоматического угадывания имени из имени переменной для анонимных функций, MDN вызывает это имя выведенной функции.
Назад, когда вопрос был задан, окончательным обсуждением этой темы была статья kangax: " Названные выражения функций демистифицированы (теперь немного устаревшие).