Именованные функции
В этом вопросе и ответах на этой странице есть серьезные злоупотребления терминологией. Нет ничего о том, является ли функция встроенной (выражение функции), которая говорит, что вы не можете назвать ее.
Используется выражение функции :
setTimeout(function doSomethingLater() { alert('In a named function.'); }, 5);
и используется оператор функции :
function doSomethingLater() { alert('In a named function.'); }
setTimeout(doSomethingLater, 5);
В обоих примерах используются именованные функции, и оба получают одинаковые преимущества, когда речь идет об инструментах отладки и профилирования!
Если имя указано (текст после «function», но перед круглыми скобками), то это именованная функция независимо от того, является ли она встроенной или объявлена отдельно. Если имя не указано, оно является «анонимным».
Примечание: T.J. указывает на то, что IE неправильно обрабатывает выражения именованных функций (см .: http://kangax.github.com/nfe/#jscript-bugs), и это важно отметить, я просто пытаюсь сделать вывод о терминологии.
Что вы должны использовать?
В ответ на ваш прямой вопрос вы должны использовать оператор именованной функции, если функцию можно было бы использовать из любого другого места в вашем коде. Если функция используется ровно в одном месте и не имеет никакого отношения ни к чему другому, я бы использовал выражение функции, если оно непомерно длинное или иным образом неуместно (по причинам стиля). Если вы используете встроенное выражение функции, то часто бывает полезно назвать его так или иначе для целей отладки или ясности кода.
Утечки памяти
Если вы называете свою функцию, используете оператор функции или используете выражение функции, это мало влияет на проблему утечки памяти. Позвольте мне попытаться объяснить, что вызывает эти утечки. Посмотрите на этот код:
(function outerFunction() {
var A = 'some variable';
doStuff();
})();
В приведенном выше коде, когда "externalFunction" завершает работу, "A" выходит из области видимости и может быть подвергнута сборке мусора, освобождая эту память.
Что если мы добавим туда функцию?
(function outerFunction() {
var A = 'some variable';
setTimeout(function(){ alert('I have access to A whether I use it or not'); }, 5);
})();
В этом коде (выше) выражение функции, которое мы передаем setTimeout, имеет ссылку на «A» (через магию замыкания), и даже после завершения «externalFunction» «A» будет оставаться в памяти до тех пор, пока тайм-аут срабатывает и функция разыменовывается .
Что если мы передадим эту функцию чему-то другому, кроме setTimeout?
(function outerFunction() {
var A = 'some variable';
doStuff(function(){ alert('I have access to A whether I use it or not'); });
})();
function doStuff(fn) {
someElement.onclick = fn;
}
Теперь выражение функции, которое мы передаем «doStuff», имеет доступ к «A», и даже после завершения «externalFunction» «A» будет оставаться в памяти до тех пор, пока есть ссылка на переданную нами функцию в doStuff . В этом случае мы создаем ссылку на эту функцию (в качестве обработчика события), и поэтому «A» будет оставаться в памяти до тех пор, пока этот обработчик события не будет очищен. (например, кто-то звонит someElement.onclick = null
)
Теперь посмотрим, что происходит, когда мы используем оператор функции:
(function outerFunction() {
var A = 'some variable';
function myFunction() { alert('I have also have access to A'); };
doStuff(myFunction);
})();
Та же проблема! «myFunction» будет очищен, только если «doStuff» не содержит ссылку на него, а «A» будет очищен только после очистки «myFunction». Неважно, использовали ли мы утверждение или выражение; важно, если ссылка на эту функцию создается в doStuff!