У випадку виразу анонімної функції, функція є анонімною - буквально, вона не має назви. Змінна, якій ви її присвоюєте, має ім’я, а функція - ні. (Оновлення: це було правдою через ES5. Починаючи з ES2015 [він же ES6], часто функція, створена з анонімним виразом, отримує справжнє ім’я [але не автоматичний ідентифікатор], читайте далі ...)
Імена корисні. Імена можна побачити у слідах стеків, стеках викликів, списках точок зупинки тощо. Імена - це хороша річ ™.
(Раніше вам доводилося остерігатися іменованих виразів функцій у старих версіях IE [IE8 і нижче], оскільки вони помилково створили два абсолютно окремі об’єкти функції у два абсолютно різні часи [детальніше у моїй статті в блозі Подвійне взяття ]. Якщо вам потрібно підтримує IE8 [!!], мабуть, краще дотримуватися анонімних виразів функцій або оголошень функцій , але уникайте іменованих виразів функцій.)
Одне ключове, що стосується іменованого виразу функції, полягає в тому, що він створює ідентифікатор у межах області з цим іменем для функції в тілі функтону:
var x = function example() {
console.log(typeof example); // "function"
};
x();
console.log(typeof example); // "undefined"
Однак станом на ES2015 багато "анонімних" виразів функцій створюють функції з іменами, і цьому передували різні сучасні механізми JavaScript, які досить розумно виводили імена з контексту. У ES2015 ваш анонімний вираз функції призводить до функції з іменем boo
. Однак навіть з ES2015 + семантика автоматичний ідентифікатор не створюється:
var obj = {
x: function() {
console.log(typeof x); // "undefined"
console.log(obj.x.name); // "x"
},
y: function y() {
console.log(typeof y); // "function"
console.log(obj.y.name); // "y"
}
};
obj.x();
obj.y();
Присвоєння імені функції виконується за допомогою абстрактної операції SetFunctionName, яка використовується в різних операціях в специфікації.
Коротка версія - це фактично будь-який раз, коли анонімний вираз функції з’являється праворуч від чогось на зразок призначення або ініціалізації, наприклад:
var boo = function() { /*...*/ };
(або це може бути, let
або const
швидше ніж var
) , або
var obj = {
boo: function() { /*...*/ }
};
або
doSomething({
boo: function() { /*...*/ }
});
(ці два останні насправді однакові) , отримана функція матиме ім'я ( boo
, у прикладах).
Існує важливий і навмисний виняток: Присвоєння властивості існуючому об’єкту:
obj.boo = function() { /*...*/ }; // <== Does not get a name
Це сталося через занепокоєння щодо витоку інформації, яке виникало, коли нова функція проходила процес додавання; деталі у моїй відповіді на інше запитання тут .