Как называть анонимную функцию в 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 функция.