Страницы

Поиск по вопросам

среда, 10 октября 2018 г.

Самовыполняющиеся функции [дубликат]

На данный вопрос уже ответили: Что в Javascript значит синтакс ( function(){…} )( param1, param2); ? 7 ответов Зачем оборачивать блоки кода на JS в самовыполняющиеся функции?


Ответ

Переменные, объявленные внутри функции, являются локальными (находятся в её области видимости). Это даёт как минимум 3 полезных момента:
"Снаружи" не "достучаться" до того, что объявлено внутри функции. Не получится случайно затереть глобальную переменную, объявив переменную с таким же именем внутри функции. Глобальная область видимости не "захламляется" данными, которые не должны быть глобальными.
Самовыполняющаяся функция (Immediately-Invoked Function Expression, IIFE) позволяет воспользоваться этими преимуществами, не создавая глобальную функцию.
var x = 1; (function() { var x = 2; var y = 3; console.log("In: " + x); //In: 2 console.log("In: " + y); //In: 3 })(); console.log("Out: " + x); //Out: 1 console.log("Out: " + y); //ReferenceError: y is not defined
Например, можно использовать самовыполняющуюся функции для того, чтобы сохранять данные, необходимые для работы функции, и которые при этом нужно хранить между вызовами функции:
var test = (function() { var count = 0; return function() { count++; console.log("Count: " + count); }; })(); test(); //Count: 1 test(); //Count: 2 console.log(count); //ReferenceError: count is not defined
Переменная count недоступна в глобальной области видимости, однако доступна внутри возвращаемой функции, так как та объявлена внутри самовыполняющейся функции, и поэтому имеет доступ к её области видимости.

Также самовыполняющаяся функция может "помочь" с сохранением промежуточных значений данных при асинхронном выполнении кода.
Например:
for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000 * i); }
Данный код будет выводить в консоль раз в секунду не числа по возрастанию, а число 10, потому что на момент вызова первой функции в setTimeout глобальная переменная i уже будет равна 10 (сначала проходят все итерации цикла, а уже потом вызывается первая функция).
Если же обернуть setTimeout в функцию и передавать ей i в качестве аргумента, то вывод будет от 0 до 9
for (var i = 0; i < 10; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000 * i); })(i); }
В данном случае переменная i в setTimeout уже не является глобальной переменной и не зависит от её изменений. Однако тут не нужно забывать о том, что если переменная является объектом, то изменение значения поля объекта "снаружи" приведёт и к изменению значения поля объекта "внутри".

Комментариев нет:

Отправить комментарий