Мое первое столкновение с немедленно вызываемыми функциональными выражениями (или сокращенно 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.