Я читал некоторые посты о замыканиях и видел это повсюду, но нет четкого объяснения, как это работает - каждый раз, когда мне просто говорили использовать его ...:
// Create a new anonymous function, to use as a wrapper
(function(){
// The variable that would, normally, be global
var msg = "Thanks for visiting!";
// Binding a new function to a global object
window.onunload = function(){
// Which uses the 'hidden' variable
alert( msg );
};
// Close off the anonymous function and execute it
})();
Хорошо, я вижу, что мы создадим новую анонимную функцию и затем запустим ее. Итак, после этого этот простой код должен работать (и он работает):
(function (msg){alert(msg)})('SO');
У меня вопрос, какая магия здесь происходит? Я думал, что когда я написал:
(function (msg){alert(msg)})
тогда новая безымянная функция будет создана как функция "" (msg) ...
но тогда почему это не работает?
(function (msg){alert(msg)});
('SO');
Почему это должно быть в одной строке?
Не могли бы вы указать мне несколько постов или дать мне объяснение?
(function (msg){alert(msg)})('SO');
работает полностью самостоятельно. Это не имеет никакого отношения к другой анонимной функции, которую вы разместили перед ней. Это две совершенно разные анонимные функции. Вы должны немедленно вызвать анонимную функцию, потому что она не имеет имени и на нее нельзя ссылаться впоследствии.Ответы:
Удалите точку с запятой после определения функции.
Над должно работать.
ДЕМО-страница: https://jsfiddle.net/e7ooeq6m/
Я обсуждал этот тип паттерна в этом посте:
JQuery и $ вопросы
РЕДАКТИРОВАТЬ:
Если вы посмотрите на спецификацию скрипта ECMA , вы можете определить функцию тремя способами. (Страница 98, Раздел 13 Определение функций)
1. Использование конструктора функций
2. Использование объявления функций.
3. Выражение функции
Поэтому вы можете спросить, в чем разница между декларацией и выражением?
Из спецификации ECMA Script:
Если вы заметили, «идентификатор» является необязательным для выражения функции. И когда вы не даете идентификатор, вы создаете анонимную функцию. Это не значит, что вы не можете указать идентификатор.
Это означает, что следующее действительно.
Важно отметить, что вы можете использовать mySum только внутри тела функции mySum, а не снаружи. Смотрите следующий пример:
Live Demo
Сравните это с
Вооружившись этими знаниями, давайте попробуем проанализировать ваш код.
Когда у вас есть код, как,
Вы создали выражение функции. И вы можете выполнить это выражение функции, заключив его в круглые скобки.
источник
Это называется функцией, вызываемой самим собой.
То, что вы делаете, когда вызываете
(function(){})
, возвращает объект функции. Когда вы добавляете()
к нему, он вызывается, и все в теле выполняется.;
Означает конец заявления, именно поэтому второй вызов терпит неудачу.источник
Одна вещь, которая меня смущает, заключается в том, что "()" - это операторы группировки.
Вот ваша основная заявленная функция.
Ex. 1:
Функции являются объектами и могут быть сгруппированы. Так что давайте разбрасывать парень вокруг функции.
Ex. 2:
Теперь вместо того, чтобы объявлять и сразу вызывать одну и ту же функцию, мы можем использовать базовую подстановку, чтобы объявить ее так, как мы ее называем.
Ex. 3.
Наконец, нам не нужен этот дополнительный foo, потому что мы не используем имя для его вызова! Функции могут быть анонимными.
Ex. 4.
Чтобы ответить на ваш вопрос, вернитесь к примеру 2. Ваша первая строка объявляет некоторую безымянную функцию и группирует ее, но не вызывает ее. Вторая строка группирует строку. Оба ничего не делают. (Первый пример Винсента.)
Но
источник
Анонимная функция не является функцией с именем "". Это просто функция без имени.
Как и любое другое значение в JavaScript, функции не нужно создавать имя. Хотя гораздо полезнее связать его с именем, как и с любым другим значением.
Но, как и любое другое значение, вы иногда хотите использовать его без привязки к имени. Это самопризывная модель.
Вот функция и число, не связанные, они ничего не делают и никогда не могут быть использованы:
Поэтому мы должны хранить их в переменной, чтобы иметь возможность использовать их, как и любое другое значение:
Вы также можете использовать синтетический сахар для привязки функции к переменной:
Но если присвоение им имен не требуется и приведет к большей путанице и снижению читабельности, вы можете просто использовать их сразу.
Здесь моя функция и мои числа не связаны с переменной, но они все еще могут быть использованы.
Сказано, что это выглядит так, как будто вызывающая функция не имеет реального значения. Но вы должны иметь в виду, что разделитель области видимости JavaScript - это функция, а не блок ({}).
Таким образом, функция, вызывающая себя, на самом деле имеет то же значение, что и блок C ++, C # или Java. Это означает, что переменная, созданная внутри, не будет «просачиваться» за пределы области видимости. Это очень полезно в JavaScript, чтобы не загрязнять глобальную область видимости.
источник
Это просто, как работает JavaScript. Вы можете объявить именованную функцию:
И назовите это:
Или вы можете объявить анонимную функцию:
И назовите это:
Или вы просто не можете связать функцию с именем:
Функции также могут возвращать функции:
Ничего не стоит, что любые переменные, определенные с помощью «var» в теле,
make_foo
будут закрываться каждой возвращаемой функциейmake_foo
. Это закрытие, и это означает, что любое изменение, внесенное в значение одной функцией, будет видно другой.Это позволяет вам инкапсулировать информацию, если вы хотите:
Просто так работает почти каждый язык программирования, кроме Java.
источник
Код, который вы показываете,
состоят из двух утверждений. Первое - это выражение, которое возвращает функциональный объект (который затем будет собирать мусор, потому что он не сохраняется). Второе - это выражение, которое дает строку. Чтобы применить функцию к строке, вам нужно либо передать строку в качестве аргумента функции при ее создании (что вы также показали выше), либо вам нужно будет на самом деле сохранить функцию в переменной, чтобы вы могли примените его позже, на досуге. Вот так:
Обратите внимание, что, сохраняя анонимную функцию (лямбда-функцию) в переменной, вы фактически даете ей имя. Следовательно, вы также можете определить обычную функцию:
источник
В резюме предыдущих комментариев:
если переменная не назначена, выдается синтаксическая ошибка. Код анализируется как оператор функции (или определение), что делает синтаксически некорректно закрывающие скобки. Добавление скобок вокруг части функции говорит интерпретатору (и программисту), что это выражение функции (или вызов), как в
Это самопризывающая функция, то есть она создается анонимно и запускается немедленно, потому что вызов происходит в той же строке, где она объявлена. Это само-вызова функции индицируется знакомый синтаксис для вызова функции без аргументов, а также добавлены круглые скобки вокруг имени функции:
(myFunction)();
.Имеется хороший SO SO обсуждение синтаксиса функции JavaScript .
источник
Этот ответ не связан строго с вопросом, но вам может быть интересно узнать, что этот тип синтаксиса не является специфическим для функций. Например, мы всегда можем сделать что-то вроде этого:
Связанные с функциями. Поскольку они являются объектами, которые наследуются от Function.prototype, мы можем делать такие вещи, как:
И вы знаете, нам даже не нужно заключать в скобки функции для их выполнения. Во всяком случае, до тех пор, пока мы пытаемся присвоить результат переменной.
Еще одна вещь, которую вы можете сделать с функциями, как только вы их объявите, - это вызвать
new
оператор над ними и получить объект. Следующее эквивалентно:источник
Есть еще одно свойство, которое имеет функция JavaScript. Если вы хотите вызвать ту же анонимную функцию рекурсивно.
источник
Мое понимание вопроса аскера таково:
Как работает эта магия:
Я могу ошибаться Тем не менее, обычная практика, с которой люди знакомы:
Причина в том, что в скобках JavaScript AKA
()
не может содержаться операторы, и когда синтаксический анализатор встречает ключевое слово функции, он знает, что нужно проанализировать его как выражение функции, а не как объявление функции.Источник: запись в блоге Выражение с немедленным вызовом функции (IIFE)
источник
примеры без скобок:
(это единственное реальное использование пустоты, афаик)
или
или
работать так же.
void
вызывает выражение для оценки, а также задания и взрыва. последний один работает с~
,+
,-
,delete
,typeof
, некоторые из унарных (void
это один, а). не работает++
,--
потому что требование переменной.разрыв строки не требуется.
источник
delete
работает. даже с'use strict';
. это тоже работает:delete (3 + 4);
Это самоисполняющаяся анонимная функция. Первый набор скобок содержит выражения, которые должны быть выполнены, а второй набор скобок выполняет эти выражения.
Питер Мишо обсуждает разницу в « Важной паре скобок» .
Это полезная конструкция при попытке скрыть переменные из родительского пространства имен. Весь код внутри функции содержится в закрытой области видимости функции, что означает, что к нему вообще нельзя получить доступ извне функции, что делает его действительно закрытым.
Видеть:
источник
Другая точка зрения
Во-первых, вы можете объявить анонимную функцию:
Тогда вы называете это:
Потому что foo = function (msg) {alert (msg);}, поэтому вы можете заменить foo следующим образом:
Но вы должны обернуть всю анонимную функцию в пару фигурных скобок, чтобы избежать синтаксической ошибки объявления функции при разборе. Тогда мы имеем,
Таким образом, это легко понять для меня.
источник
Когда вы сделали:
Вы закончили функцию раньше
('SO')
из-за точки с запятой. Если вы просто напишите:Это будет работать.
Рабочий пример: http://jsfiddle.net/oliverni/dbVjg/
источник
Простая причина, по которой это не работает, не в том, что
;
указывается конец анонимной функции. Это связано с тем, что без()
завершения вызова функции это не вызов функции. Это,Если вы вызываете
result = help();
это вызов функции и вернет true.Если вы звоните,
result = help;
это не звонок. Это назначение, при котором помощь обрабатывается как данные, которые должны быть присвоены результату.Вы сделали объявление / создание анонимной функции путем добавления точки с запятой,
и затем попытался вызвать его в другом выражении, используя только круглые скобки ... Очевидно, потому что у функции нет имени, но это не будет работать:
Интерпретатор видит круглые скобки во второй строке как новую инструкцию / инструкцию, и поэтому он не работает, даже если вы сделали это так:
Это все еще не работает, но работает, когда вы удаляете точку с запятой, потому что интерпретатор игнорирует пробелы и каретки и видит весь код как одно утверждение.
Вывод: вызов функции не является вызовом функции без
()
конца, если только при определенных условиях, таких как вызов другой функцией, то есть onload = 'help', будет выполняться функция справки, даже если круглые скобки не были включены. Я полагаю, что setTimeout и setInterval также позволяют этот тип вызова функции, и я также полагаю, что интерпретатор в любом случае добавляет скобки за кулисы, что возвращает нас к «вызову функции не является вызовом функции без скобок».источник
Это распространенный метод использования анонимной функции в качестве замыкания, которую используют многие платформы JavaScript.
Эта функция вызывается автоматически при компиляции кода.
Если поместить
;
в первую строку, компилятор обрабатывает его как две разные строки. Таким образом, вы не можете получить те же результаты, что и выше.Это также можно записать как:
Для более подробной информации, посмотрите на JavaScript / анонимные функции .
источник
Анонимные функции - это функции, которые динамически объявляются во время выполнения. Они называются анонимными функциями, потому что им не дают имя так же, как обычным функциям.
Анонимные функции объявляются с использованием оператора функции вместо объявления функции. Вы можете использовать оператор функции, чтобы создать новую функцию везде, где допустимо поместить выражение. Например, вы можете объявить новую функцию в качестве параметра для вызова функции или назначить свойство другого объекта.
Вот типичный пример именованной функции:
function flyToTheMoon () {alert ("Zoom! Zoom! Zoom!"); } flyToTheMoon (); Вот тот же пример, созданный как анонимная функция:
var flyToTheMoon = function () {alert ("Zoom! Zoom! Zoom!"); } flyToTheMoon ();
Для подробностей, пожалуйста, прочитайте здесь:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
источник
IIFE просто разделяет функцию и скрывает
msg
переменную, чтобы не «загрязнять» глобальное пространство имен. В действительности, просто сделайте это простым и делайте как ниже, если вы не создаете сайт за миллиард долларов.Вы можете присвоить пространству имен свое
msg
свойство, используя шаблон модуля «Выявление», например:источник
Под анонимными функциями подразумевается разовая сделка, при которой вы определяете функцию на лету, чтобы она генерировала выходные данные из предоставленных вами входных данных. За исключением того, что вы не предоставили вход. Вместо этого вы написали что-то во второй строке («SO»); - независимое утверждение, которое не имеет ничего общего с функцией. Что вы ожидали? :)
источник
var foo = function() {};
. Все остальное в порядке, хотя.