Вторник, 30 мая, 2017

Самовызывающиеся функции в Javascript

комментарии: 6

Javascript кажется немного странным языком, который иногда делает странные вещи. Такие мысли могут возникнуть, если не следить за лучшими практиками и не быть знакомым со стандартом ECMA. Странности встречаются и в синтаксисе и семантике. Одна из таких вещей – это самовызывающиеся функции (self-invoking functions).

Cинтаксис:

(function () {
    // код функции 
 }());

Главной идеей является то, что анонимная функция вызывается сразу после своего объявления. Преимущество от использования самовызывающихся функций вы получите, если нужно выполнить код один раз и сохранить его резульататы во "внешней среде" (без объявления глобальных переменных).

Например, для небольшой веб-страницы можно написать обработчики событий для элементов на странице. Самовызывающиеся функции подходящее средство для такой ситуации.

Что фактически будет происходить?

Как видно из примера выше, мы определили анонимную функцию и нет никаких глобальных переменных. И даже нет локальных, за исключением тех, что мы будем использовать внутри функции. Мы не храним нигде ссылку на эту функцию. Нигде не храним возвращаемое значение. Так только функция инициализирована, она тут же вызывается.

Это может быть удобным вариантом инициализации, например, мы инициализируем и прикрепляем функции обработчиков событий один раз, после объявления функции вызываем ее, и теряем с ней связь.

Существует несколько видов синтаксиса этих функций. Хотя разница очень мала, но приведем примеры. Дуглас Крокфорд, один из разработчиков Javascript, считает правильной такую запись самовызывающейся функции:

(function () {
    //body
}());

А вот другой вариант, который Крокфорд, называет "собачьи яйца" (dog balls).

(function () {
    //body
})();

Некоторые считают, что второй вариант более удобен.

Такой вариант тоже работает, но почему-то нигде не встречается:

function () {
    //body
}();

В самовызывающуюся функцию можно передавать параметры. Это общая практика передачи ссылок на глобальные объекты:

(function (w, d, $) {
   //body
}(window, document, jQuery));

Не рекомендуется передавать слишком много аргументов (больше трех-четырех), потому что если функция становится больше в размерах, то нужно постоянно скроллить, чтобы вспомнить нужный параметр, а если их много то это приходится делать довольно часто. Если вы легко запоминаете аргументы, то нужно быть благосклонным к тем, кто будет читать код после вас.

И самое интересное, ради чего и замыслился весь этот пост, самовызывающуюся функцию можно использовать в модульном паттерне (module pattern). Мы сохраняем ссылку на возвращаемое значение, а именно на API модуля:

var module = (function () {
    //private
    return {
    //public
    }
}());

Статей про модульный паттерн существует очень много, очень удобная штука для тех, кто писал классы в C#, С++ т.п.

Итак, самовызывающиеся функции – это функции, вызывающие сами себя, использовать их или нет зависит от вас, но понимать их надо. Иногда их еще называют как немедленно исполняемые функции (Immediately Invoked Functions).

Комментарии

Василий Мажекин Василий Мажекин 28 июля, 2014, 08:52
В общем, в первой половине статьи самовызывающиеся функции, это просто некая рамка, видимо для читабельности, оформления смыслового блока, и чтобы внутренние переменные не действовали глобально, а во второй еще плюс быстрое создание модуля, то есть описали модуль и сразу создали его...
Денис Денис 19 ноября, 2015, 02:18
этот вариант не работает: function () { //body }();
Даниил Даниил 27 мая, 2016, 10:29
правильно будет вот так: var a = function() { //body }();
Александр Александр 15 сентября, 2016, 01:07
Или (function () { //body }()); Или (function () { //body })(); Нигде не встречается из-за того что противоречит правилам языка.
Мирослав Мирослав 24 января, 2017, 04:03
Александр, ничему не противоречит. Просто если писать function(){}() - когда читаешь функцию, неочевидно что она самовызывающаяся. Поэтому используют два других вариантаю
фщаодоыьвщпы фщаодоыьвщпы 22 февраля, 2017, 04:31
Этот вариант не будет работатьfunction () { //body }(); Нужно добавить знак '!', т.е. в итоге будет - !function(){console.log(this)}();

 

Добавить комментарий

Войти через Twitter Войти через Facebook Войти через ВКонтакте Войти через Github Войти через Google Войти через LinkedIn

Copyright © 2013 All Rights Reserved for CodeHint.ru      Powered by Windows Azure