Ответ для ECMAScript 2015 (он же «ES6») :
Да .Начиная с ES2015, функция, созданная выражением анонимной функции, назначенным свойству объекта, получает имя этого свойства объекта. Когда я пишу это 11 мая 2015 года, никакой другой движок JavaScript, кроме «Project Spartan» от Microsoft для Windows 10 Preview, не поддерживает это (да, вы правильно прочитали, M $ попал туда до Mozilla или Google) , но это в спецификации, и реализации наверстают упущенное. Обновление : по состоянию на октябрь 2016 г. последние версии Chrome реализуют Function#name
и различныеправила присвоения имен;Firefox по-прежнему нет, но они туда доберутся.
Так, например, в ES2015 создается функция с именем "foo ###", где ### - это 1-3 цифры:
const dynamicName = "foo" + Math.floor(Math.random() * 1000);
const obj = {
[dynamicName]() {
throw new Error();
}
};
const f = obj[dynamicName];
// See its `name` property (Edge and Chrome for now, eventually Firefox will get it)
console.log("Function's `name` property: " + f.name + " (see compatibility note)");
// We can see that it truly has a name (even in Firefox which doesn't have the `name` property yet) via an exception:
try {
f();
} catch (e) {
console.log(e.stack);
}
Использует новое оцененное имя свойства ES2015 и синтаксис нового метода для создания функции и присвоения ей динамического имени, а затем получает ссылку на нее в f
.(Это также будет работать с [dynamicName]: function() { }
, синтаксис метода не требуется, синтаксис функции в порядке.)
Ответ для ECMAScript 5 (с 2012 г.):
Нет.Вы не можете сделать это без eval
или его двоюродного брата конструктора Function
.Вы можете выбрать:
Вместо этого используйте анонимную функцию.Современные движки делают что-то, чтобы помочь с отладкой.
Используйте eval
.
Используйте конструктор Function
.
Подробности:
Вместо этого используйте анонимную функцию.Многие современные движки покажут полезное имя (например, в стеках вызовов и т. Д.), Если у вас есть хорошее, однозначное выражение var name = function() { ... };
(показывающее имя переменной), даже если технически функция не делаету меня нет имени.В ES6 функции, созданные таким образом, на самом деле будут иметь имена, если они будут выведены из контекста.В любом случае, если вам нужно действительно определенное во время выполнения имя (имя, полученное из переменной), вы в значительной степени застряли.
Используйте eval
.eval
- зло , когда вы можете избежать этого , но со строками, которые вы полностью контролируете, в контролируемой вами области, с пониманием затрат (вы запускаете анализатор JavaScript)Если вы делаете то, что вы не можете сделать иначе (как в этом случае), это нормально, если вам действительно нужно это сделать.Но если вы не управляете строкой или областью действия или не хотите платить за нее, вам придется жить с анонимной функцией.
Вот как выглядит опция eval
:
var name = /* ...come up with the name... */;
var f = eval(
"(function() {\n" +
" function " + name + "() {\n" +
" console.log('Hi');\n" +
" }\n" +
" return " + name + ";\n" +
"})();"
);
Живой пример | Живой источник
Это создает функцию с именем, которое мы придумали во время выполнения, без утечки имени в содержащую область (и без запуска некорректной обработки выражений именованных функций в IE8 и более ранних версиях), присваивая ссылку на эту функцию f
.(И он прекрасно форматирует код, так что пошаговое выполнение его в отладчике легко.)
Раньше это не использовалось для правильного присвоения имени (что удивительно) в более старых версиях Firefox.Что касается текущей версии их движка JavaScript в Firefox 29, он делает.
Поскольку он использует eval
, созданная вами функция имеет доступ к области, в которой она была создана, что важно, если вы 'аккуратный кодер, который избегает глобальных символов.Так что это работает, например:
(function() {
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
var name = /* ...come up with the name... */;
var f = eval(
"(function() {\n" +
" function " + name + "() {\n" +
" display('Hi');\n" + // <=== Change here to use the
" }\n" + // function above
" return " + name + ";\n" +
"})();"
);
})();
Используйте конструктор Function
, как показано в этой статье Marcos Cáceres :
var f = new Function(
"return function " + name + "() {\n" +
" display('Hi!');\n" +
" debugger;\n" +
"};"
)();
Живой пример | Живой источник
Там мы создаем временную анонимную функцию (созданную с помощью конструктора Function
) и вызываем ее; эта временная анонимная функция создает именованную функцию, используя выражение именованной функции. То, что будет , вызовет некорректный дескриптор выражений именованных функций в IE8 и более ранних версиях, но это не имеет значения, потому что побочные эффекты этого ограничены временной функцией.
Это короче, чем версия eval
, но имеет проблему: функции, созданные с помощью конструктора Function
, делают , а не , имеют доступ к области, в которой они были созданы. Таким образом, приведенный выше пример использования display
потерпит неудачу, потому что display
не будет находиться в области видимости созданной функции. ( Вот пример сбоев. Источник ). Так что не вариант для аккуратных кодеров избегать глобальных символов, но полезен для тех случаев, когда вы хотите отсоединить сгенерированную функцию от области, в которой вы ее генерируете.