Мое первое столкновение с немедленно вызываемыми функциональными выражениями (или сокращенно IIFE) оставило меня несколько озадаченным.
Для тех, кто не знает, о чем я, они выглядят примерно так:
(function(name){ console.log("hello " + name); })("Moe");
Помимо создания изящной игры на выпивку каждый раз, когда вы замечаете скобку, в этом есть глубокая логика. Но прежде чем обращаться к ним, стоит быстро просмотреть различные типы объектов-функций, которые JavaScript позволяет нам создавать.
Функциональные операторы и функциональные выражения
Первый формат объекта функции, с которым вы, вероятно, столкнетесь, — это операторы/объявления функций, как в примере ниже:
function greet(name) { console.log("hello " + name); } greet("Moe"); //=> this prints "hello Moe"
Эти функциональные объекты поднимаются на этапе создания контекста выполнения, в котором они находятся, что означает, что они доступны для использования в любой точке кода. Таким образом, вы даже можете вызвать функцию до того, как она будет объявлена:
greet("moe"); // => This will also print "hello Moe" function greet(name) { console.log("hello " + name) }
Другой способ создания объектов-функций — использование функциональных выражений, как показано ниже:
var greet = function(name) { console.log("hello " + name) }
Ключевое отличие здесь в том, что вместо того, чтобы объявлять функцию заранее, мы присваиваем ее переменной. Вы также заметите отсутствие имени функции, вместо этого у нас есть анонимная функция, назначенная переменной.
В отличие от объявлений функций, функциональные выражения не поднимаются при создании, а назначенная им переменная устанавливается в undefined и назначается только что созданному функциональному объекту, когда синтаксический анализатор достигает этой строки кода.
Это также означает, что мы не можем вызывать функцию до того, как она будет определена, как с объявлениями функций, и, следовательно, она всегда должна вызываться после определения:
greet("moe"); // => this will return an error var greet = function(name) { console.log("hello " + name) } greet("moe"); // => this will print "hello moe"
Это функциональное выражение, потому что в JavaScript выражение — это то, что возвращает значение. В этом случае возвращаемое значение — это сам объект функции, который создается «на лету» после того, как синтаксический анализатор достигает этой строки кода.
Так что же такое немедленно вызываемое функциональное выражение?
Проще говоря, IIFE — это функциональное выражение, которое вызывается сразу же после создания. Давайте еще раз взглянем на предыдущий пример:
(function(name) { console.log("hello " + name })("moe"); //=> this prints "hello moe"
Вы заметите круглые скобки «()» в самом конце, используемые для вызова функции с аргументом. Это означает, что эта функция выполняется сразу же после ее определения и, следовательно, выводит на консоль «hello moe» без необходимости вызывать ее отдельно, например:greet(«moe»);
Так почему же это функциональное выражение?
Помните, как я сказал, что выражения в JavaScript возвращают значение? Что ж, это именно то, что мы здесь делаем — возвращаем объект функции на лету, и это стало возможным благодаря скобкам, заключенным вокруг всей функции.
Видите, синтаксический анализатор может быть слишком умным для своего же блага, и в отсутствие круглых скобок первые символы, с которыми он столкнется, — это ключевое слово «функция», означающее, что синтаксический анализатор будет ожидать, что мы создадим функцию. декларация. Однако, заключая функцию в круглые скобки, мы обманываем синтаксический анализатор, заставляя его думать, что это выражение, и, следовательно, возвращая значение, которое в данном случае будет объектом функции.
Зачем?
Итак, теперь, когда мы знаем, что они из себя представляют, вы, как и я, возможно, задавались вопросом: «Хорошо, круто, но что с того?
Все сводится к конфиденциальности и предотвращению конфликта переменных. Это связано с тем, что переменные, объявленные внутри IIFE, доступны только внутри его области действия и, следовательно, не могут быть доступны во внешней среде:
(function(){ var nuclearCodes = 1234; })(); console.log(nuclearCodes) //=> this returns an error
Это также работает в обе стороны, поскольку ваши переменные в IIFE не рискуют конфликтовать с переменными во внешней среде, которые могут иметь похожее имя. Поэтому вы найдете множество фреймворков/библиотек, таких как jQuery, завернутые в IIFE, чтобы их можно было легко внедрить в приложение, не мешая коду приложения.
Хотя вы можете подумать, почему бы просто не использовать обычную функцию и не вызывать ее? Что ж, выбрав IIFE, вы избежите необходимости засорять глобальное пространство имен ненужными именами переменных, а также снизите риск случайного вызова функции в другом месте.
Пока это все.
Ну вот и все. IIFE — еще один довольно приятный инструмент в наборе инструментов JavaScript. Есть предположение, что они могут оказаться менее распространенными в ES6, но это то, что мне придется исследовать самому.
До тех пор.
M.