Как называть анонимную функцию в JavaScript имеет значение?
Я анализирую следующие два URL-адреса с сайта Джона Ресига, но я не понимаю, как внесение имени анонимной функции имеет значение.
Мое понимание заключается в том, что имя, присвоенное анонимной функции, может использоваться только внутри определения функции и нигде за ее пределами, но в следующих ссылках это делает огромную разницу
Любое объяснение или ссылка будут большой помощью.
Я все еще путаюсь со следующими строками в # 14
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
Как метод Samurai.yell все еще способен указывать ninja.yell, когда ниндзя теперь указывает на пустой объект.
Единственное отличие между # 13 и # 14 заключается в предоставлении имени выражения функции в # 14.
Является ли ninja.yell COPIED кричать и не ссылаться, или это выражение функции NAMED имеет глобальную область видимости в таком сценарии?
То же самое происходит в # 13 и # 14, только разница в том, что функция названа в # 14 и не обозначена в # 13 плюс ninja = {} в # 14 и ninja = null в # 13. Есть ли скрытая концепция об ИМЕНИ FUNCTION EXPRESSIONS, которую я пропускаю, что делает # 14 работоспособным и # 13 неработоспособным.
Ответы
Ответ 1
Не пытаться вести боевые действия с Колинком, но он слишком сильно говорит, что это НЕ хороший пример. То, что связано с № 14 (в общих ссылках), называется выражением функции (другое объявление из объявлений функций). Независимо от того, где передается эталонная функция, если вы называете свое выражение функции, у него всегда будет возможность вызвать себя изнутри самого себя. Это имя, которое вы даете своему выражению функции, - это имя, которое только оно знает; он не существует ни в какой внешней области.
Смотрите здесь и здесь на MDN, для дальнейшее обсуждение выражений функций и функций. Вторая ссылка внизу имеет заголовок о названных функциональных выражениях. Он использует; см. my Gist для примера одноразовой рекурсивной функции, которая ничего не добавляет к области локальной или глобальной переменной (полезная для одноразового обхода DOM, например).
Кроме того, Тобиас (в своем ответе здесь) указывает на другие полезные применения названных функциональных выражений, а именно в отладке.
Ответ 2
в примерах внутри вы можете пропустить дополнительный доступ к объекту ниндзя в # 13
анонимное закрытие (требуется доступ к объекту ninja
, хотя мы уже в этом контексте):
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
именованное закрытие может быть вызвано непосредственно:
var ninja = {
yell: function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
};
еще одно преимущество заключается в том, что именованные блокировки позволяют осуществлять стекирование:
поэтому предположим, что вы выполните:
(function fooBar() { console.log(brazl); })();
// will create an error with "fooBar" in the stack trace instead of "anonymous function"
EDIT: хотя это может выглядеть как накладные расходы, иногда это помогает отлаживать во время разработки, и, например, YUICompressor и Closure Compiler могут отделять эти имена, если они по существу не нужны.
Ответ 3
В первом случае метод yell
пытается получить доступ к ninja.yell
, независимо от того, какой объект вызывает его. В то время как во втором он пытается вызвать yell
, который существует, потому что функция названа.
Это НЕ хороший пример. Хороший пример использовал бы this.yell
вместо ninja.yell
, тем самым получая метод yell
от текущего объекта.
Ответ 4
Сайт http://kangax.github.com/nfe/ - отличная ссылка. Да, поскольку это выражение функции, имя будет доступно только внутри (например, для рекурсивных вызовов, как в демонстрации), а также помогает для отладки (например, в трассировке стека), поскольку оно устанавливает свойство name
функция.