Зачем оборачивать блоки кода на JS в самовыполняющиеся функции?
-
2Пример приведите, пожалуйста. – Kromster Dec 01 '15 at 17:54
-
2Чтобы переменные оставались внутри функции и не захламляли внешний scope: fiddle. – Regent Dec 01 '15 at 18:07
-
@VladD всё-таки хотелось бы получить пример от автора, чтобы быть уверенным, что речь вообще именно об этом. Надо было эту оговорку в комментарий свой предыдущий добавить. – Regent Dec 01 '15 at 18:16
-
@Regent: Ну, вроде бы самовыполняющаяся функция — устоявшийся термин. – VladD Dec 01 '15 at 18:17
-
И тема об областях видимости важна, т. к. одно из фундаментальных отличий js от других языков. – VladD Dec 01 '15 at 18:18
-
А пример чего вы хотите получить? Самовыполняющейся функции? – VladD Dec 01 '15 at 18:18
-
Такой вопрос у меня был в домашнем задании. Примера нет. И информацию найти не получается. – Gavrenko Katerina Dec 01 '15 at 18:24
-
1@GavrenkoKaterina: Вопрос на самом деле касается одного из основополагающих принципов javascript. – VladD Dec 01 '15 at 18:28
-
1@VladD я скромный (немногим более развёрнутый, чем в комментарии) ответ почти написал, но вот полный и развёрнутый ответ по поводу замыканий и областей видимости вряд ли потяну. – Regent Dec 01 '15 at 18:31
-
Гуглите IIFE ;) – Dmitriy Simushev Dec 01 '15 at 18:32
-
http://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript – Grundy Dec 01 '15 at 18:36
-
1@Regent запостите, а потом правками улучшите. Или запостите как вики, тогда и другие дополнят – Kromster Dec 01 '15 at 18:36
1 Answers
Переменные, объявленные внутри функции, являются локальными (находятся в её области видимости). Это даёт как минимум 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 уже не является глобальной переменной и не зависит от её изменений. Однако тут не нужно забывать о том, что если переменная является объектом, то изменение значения поля объекта "снаружи" приведёт и к изменению значения поля объекта "внутри".
- 19,134