Какова цель оборачивания целых файлов JavaScript в анонимные функции, например, “(function(){ … })()”?
Я много читал о Javascript в последнее время и заметил, что в .js файлах, которые должны быть импортированы, весь код обернут следующим образом:
(function() {
...
код
...
})();
В чем причина такого подхода, вместо простого набора конструкторских функций?
5 ответ(ов)
Это называется замыканием. Оно фактически изолирует код внутри функции, чтобы другие библиотеки не могли с ним вмешиваться. Это похоже на создание пространства имен в компилируемых языках.
Пример. Допустим, я пишу:
(function() {
var x = 2;
// делаем что-то с x
})();
Теперь другие библиотеки не могут получить доступ к переменной x
, которую я создал для использования в своей библиотеке.
В JavaScript, выполняемом в браузере, по сути, существует только два эффективных уровня видимости: область видимости функции и глобальная область видимости.
Если переменная не находится в области видимости функции, значит, она находится в глобальной области видимости. Глобальные переменные обычно считаются плохой практикой, поэтому полезно использовать конструкции, позволяющие библиотекам изолировать свои переменные от глобального контекста.
Вы можете использовать замыкания (closures) в качестве данных в более сложных выражениях, как показано в этом методе определения поддержки браузером некоторых объектов HTML5.
navigator.html5 = {
canvas: (function() {
var dc = document.createElement('canvas');
if (!dc.getContext) return 0;
var c = dc.getContext('2d');
return typeof c.fillText == 'function' ? 2 : 1;
})(),
localStorage: (function() {
return !!window.localStorage;
})(),
webworkers: (function() {
return !!window.Worker;
})(),
offline: (function() {
return !!window.applicationCache;
})()
}
В этом примере мы создаем объект navigator.html5
, в котором свойства инициализируются с помощью немедленно вызываемых функций. Каждая функция проверяет поддержку соответствующего HTML5 функционала и возвращает нужное значение: например, для canvas
проверяется наличие метода getContext
, а для localStorage
— существует ли объект window.localStorage
. Таким образом, мы можем динамически определять доступные функции браузера.
В дополнение к тому, чтобы держать переменные локальными, есть очень удобное применение, когда вы пишете библиотеку с использованием глобальной переменной. Вы можете дать ей более короткое имя переменной для использования внутри библиотеки. Это часто применяется при написании плагинов для jQuery, поскольку jQuery позволяет отключать переменную \(от jQuery с помощью jQuery.noConflict(). В случае, если\) отключен, ваш код все равно может использовать $ и не сломается, если вы просто сделаете так:
(function($) { ...код... })(jQuery);
- Чтобы избежать конфликтов с другими методами/библиотеками в одном контексте,
- Избегайте глобальной области видимости, сделайте её локальной,
- Это поможет ускорить процесс отладки (при локальной области видимости),
- В JavaScript существует только функциональная область видимости, что также поможет при компиляции кода.
Каков объем видимости переменных в JavaScript?
Что такое конструкция (function() { } )() в JavaScript?
JavaScript: Знак плюс перед функциональным выражением
Определение глобальной переменной в функции JavaScript
Проверка соответствия строки регулярному выражению в JS