Простая функция JavaScript с немедленным вызовом не работает... почему?
Кто-нибудь может объяснить, почему это работает:
var sayHello = function (name) {
alert("Hello there " + name + "!");
}("Mike");
Пока этого нет:
function sayHello (name) {
alert("Hello there " + name + "!");
}("Mike");
Майк торф
6 ответов
Все, что вам нужно понять, это разница между FunctionExpression и FunctionDeclaration в Javascript.
Когда вы окружаете функцию круглыми скобками -
(function sayHello (name) {
alert("Hello there " + name + "!");
})("Mike");
- Вы, технически, применяете к нему оператора группировки. После применения общее производство перестает быть FunctionDeclarataion, а является FunctionExpression. Сравнить -
function foo(){ } // FunctionDeclaration
(function foo(){ }); // FunctionExpresson
typeof function(){ }; // FunctionExpression
new function(){ }; // FunctionExpression
FunctionExpression (в отличие от FunctionDeclaration), как и любой другой MemberExpresson, может быть дополнен аргументами ("(" и ")") и приведет к вызову функции. Именно поэтому функция вызывается в вашем первом примере, а не во втором.
Обратите внимание, что функция FunctionExpression может иметь необязательные идентификаторы(в отличие от FunctionDeclaration, которые всегда должны иметь один), поэтому вы можете легко опустить "sayHello" и получить так называемое выражение анонимной функции -
(function(){
alert('...');
});
Вы можете проверить мою статью о выражениях именованных функций, в которой более подробно рассматриваются тонкие детали различий между выражениями функций и объявлениями функций.
Ваш второй код на самом деле:
function sayHello (name) {
alert("Hello there " + name + "!");
}
("Mike");
Итак, вы сначала объявляете функцию "sayHello", а затем выполняете "выражение":
("Mike");
который ничего не делает.
Это будет работать:
(function sayHello (name) {
alert("Hello there " + name + "!");
})("Mike");
Обратите внимание на символы, заключающие в себе функцию. Вы также можете удалить имя функции "sayHello", и оно все равно будет работать. Насколько почему? Я не уверен. Может быть, это то, что, присваивая его переменной и не используя обертки (), вы фактически присваиваете его sayHello, а затем выполняете say hello, а не анонимную функцию.
var sayHello = function (name) {
alert("Hello there " + name + "!");
}("Mike");
Это создает анонимную функцию и вызывает ее сразу с параметром "Mike". Затем возвращаемое значение этого вызова функции присваивается переменной sayHello
,
function sayHello (name) {
alert("Hello there " + name + "!");
}("Mike");
Это просто определяет нормальную функцию с именем sayHello
и оператор функции заканчивается после закрытия}. Затем следует утверждение ("Майк"), которое является действительным, но ничего не делает.
Окружение определения функции в ()
перед звонком работает:
(function sayHello(name) {
alert("Hello there " + name + "!");
})("Mike");
// however --
alert(typeof sayHello); // undefined
Так что если вы хотите сделать что-то подобное - вы можете просто сделать это анонимной функцией:
(function(name) {
alert("Hello there " + name + "!");
})("Mike");
И я не уверен, что это требуется - но для безопасности - всякий раз, когда я использую закрывающее устройство, я всегда оборачиваю его ()
Отредактировано, потому что мой ответ неправильно прочитал оригинальное сообщение:
Поскольку ваша функция больше не назначается как лямбда-функция для значения, последующий вызов функции с помощью ("Mike") не будет работать, так как нет значения для вызова. Как другие предлагали заключить в скобки, чтобы создать временную переменную, вы все равно сможете вызвать анонимную функцию:
(function sayHello (name) {
alert("Hello there " + name + "!");
})('Mike');