Зачем использовать именованные выражения функций?


У нас есть два разных способа для выполнения выражения функции в JavaScript:

выражение именованной функции (NFE):

var boo = function boo () {
  alert(1);
};

анонимное выражение функции:

var boo = function () {
  alert(1);
};

и оба они могут быть вызваны с boo();. Я действительно не могу понять, почему/когда я должен использовать анонимные функции и когда я должен использовать именованные выражения функций. Какая между ними разница?

5 78

5 ответов:

в случае анонимного выражения функции, функция аноним - буквально, у него нет названия. Переменной вы присваиваете ему имя, но не. (обновление: это было верно через ES5. Начиная с ES2015 [aka ES6], часто функция, созданная с анонимным выражением, получает истинное имя, читайте дальше...)

имена полезны. Имена можно увидеть в трассировках стека, стеках вызовов, списках точек останова и т. д. Имена хорошая вещь.™

вы должны остерегаться именованных выражений функций в более старых версиях IE( IE8 и ниже), потому что IE ошибочно создает два совершенно отдельных объекта функций в два совершенно разных времени (подробнее в моей статье в блоге два). Если вам нужно поддерживать IE8, вероятно, лучше придерживаться анонимных выражений функций или функции декларации, но не по имени функции выражения.

по состоянию на ES2015, однако, многие" анонимные " выражения функций создают функции с именами, и это было предшествовано различными современными движками JavaScript, которые довольно умны в выводе имен из контекста. В ES2015 ваше анонимное выражение функции приводит к функции с именем boo. Это разбросано по всей спец вместо того, чтобы быть определенным в одном месте с кучей правил: Поиск вхождений " SetFunctionName", в настоящее время находится в:

в короткая версия-это в основном любое время, когда анонимное выражение функции появляется в правой части чего-то вроде назначения или инициализации, например:

var boo = function() { /*...*/ };

(или это может быть let или const, а не var) или

var obj = {
    boo: function() { /*...*/ }
};

или

doSomething({
    boo: function() { /*...*/ }
});

(эти последние два действительно одно и то же), полученная функция будет иметь имя (boo, в примерах).

есть важное и преднамеренное исключение: присвоение свойству существующего объекта:

obj.boo = function() { /*...*/ }; // <== Does not get a name

это было из-за проблем утечки информации, возникших, когда новая функция проходила процесс добавления; подробности в моем ответе на другой вопрос здесь.

функции именования полезны, если им нужно ссылаться на себя (например, для рекурсивных вызовов). Действительно, если вы передаете выражение литеральной функции в качестве аргумента непосредственно другой функции, это выражение функции не может непосредственно ссылайтесь на себя в строгом режиме ES5, если он не назван.

например, рассмотрим следующий код:

setTimeout(function sayMoo() {
    alert('MOO');
    setTimeout(sayMoo, 1000);
}, 1000);

было бы невозможно написать этот код достаточно чисто, если бы выражение функции передавалось setTimeout были анонимными; нам нужно было бы назначить его переменной вместо этого до setTimeout звонок. Этот способ, с выражением именованной функции, немного короче и аккуратнее.

исторически было возможно написать такой код, даже используя анонимное выражение функции, используя arguments.callee...

setTimeout(function () {
    alert('MOO');
    setTimeout(arguments.callee, 1000);
}, 1000);

... но arguments.callee устарело, и прямо запрещено в строгом режиме ES5. Поэтому MDN советует:

избежать используя arguments.callee() или присвоение выражениям функций имени или используйте объявление функции, где функция должна вызвать себя.

(выделено мной)

если функция задана как выражение функции, ей можно дать имя.

Он будет доступен только внутри функции (кроме IE8-).

это имя предназначено для надежного рекурсивного вызова функции, даже если оно записано в другую переменную.

обратите внимание, что при объявлении функции это не может быть сделано. Это" специальное " внутреннее имя функции указывается только в синтаксисе выражения функции.

var f = function sayHi(name) {
  alert( sayHi ); // Inside the function you can see the function code
};

alert( sayHi ); // (Error: undefined variable 'sayHi')

В дополнение, имя Nfe (именованное выражение функции) не может быть перезаписано:

var test = function sayHi(name) {
  sayHi = "тест"; // try to redefine
  alert( sayHi ); // function... (redefinition is unsuccessful )
};

test();

использование именованных выражений функций лучше, когда вы хотите иметь возможность ссылаться на рассматриваемую функцию без необходимости полагаться на устаревшие функции, такие как arguments.callee.

вы всегда должны использовать именованные функциональные выражения.

  1. вы можете использовать имя этой функции, когда вам нужна рекурсия.

2.Анонимные функции не помогают при отладке, так как вы не можете видеть имя функции, которая вызывает проблемы.

3.Когда вы не называете функцию, позже ее труднее понять, что она делает.Дать ему имя делает его легче понять.

var foo = function bar() {
 //some code...
};
foo();
bar(); // Error!

вот, например, так строка имени используется в выражении функции, она не объявляется во внешней области видимости.При использовании именованных выражений функции имя выражения функции заключено в его собственную область.