#javascript #design-patterns #iife
#javascript #шаблоны проектирования #iife
Вопрос:
Просто хотел узнать, было ли это хорошей практикой JavaScript.
Допустим, у меня есть много веб-страниц, которые все вызывают функцию инициализации «init ()», было бы правильно использовать IIFE внутри моего шаблона для запуска функции при каждой загрузке скрипта?
var foo = (function() {
var bar = "something";
(function init() {
// Do something crazy that's gonna be the same across all my web pages
// like adding an event listener or something
// ...
document.write('page init...');
}());
function privatePage1() {
// This stuff is gonna be used only in page1.html via foo.privatePage1
document.write('page 1' bar);
}
function privatePage2() {
// This stuff is gonna be used only in page2.html via foo.privatePage2
document.write('page 2' bar);
}
return {
privatePage1: privatePage1,
privatePage2: privatePage2
}
}());
Комментарии:
1. Вы должны показать более релевантный код, прежде чем мы сможем предложить правильный ответ для вашего случая. Использование анонимных функций часто является хорошей практикой, потому что утечка меньше переменных.
Ответ №1:
Это довольно субъективная область, но вот мое мнение:
-
Когда вы используете шаблон модуля, вы предоставляете ограниченный набор функций остальной части вашего кода. По сути, это мини-библиотека.
-
В общем, я бы не ожидал, что библиотека будет что-либо делать при ее загрузке, кроме шагов инициализации, которые полностью являются внутренними для библиотеки (например, настройка конфигурации, создание нескольких необходимых объектов и т. Д.) — Ничего, что действительно влияет на DOM или иным образом существенно изменяет среду (вот почемуЯ никогда не был полностью доволен такими библиотеками, как Date.js или Прототип, который изменяет прототипы базовых объектов).
-
Для этого есть несколько причин, но главная из них заключается в том, что я не хочу беспокоиться о порядке загрузки моих библиотек / модулей, кроме простого управления зависимостями. Независимые модули вообще не должны влиять друг на друга. Когда вы манипулируете DOM в своем модуле во время загрузки, рано или поздно вы поймете, что другая часть вашего кода ожидает, что DOM будет находиться в определенном состоянии в определенное время, и что теперь вам нужно заботиться о том, загружаете ли вы свой модуль до или после этого времени. Это дополнительная сложность, которая, по сути, скрыта в теге script, который загружает ваш модуль.
-
Другой проблемой здесь является переносимость и адаптивность. Возможно, вы захотите использовать свой модуль в другом проекте с другой настройкой DOM. Возможно, вы захотите передать другой элемент DOM или переменную конфигурации
init()
функции на определенной странице. Если вы выполняетеinit()
автоматически, вы теряете возможность настройки.
Итак, что я обычно делаю, так это устанавливаю init()
метод в качестве атрибута возвращаемого объекта модуля:
var foo = (function() {
function init() {
// Do something crazy that's gonna be the same across all my web pages
}
//...
return {
init: init,
// etc
}
}());
а затем вызывайте его по мере необходимости в другом месте моего кода:
foo.init();
Да, это добавляет дополнительную строку избыточного кода к инициализации для всех моих страниц (хотя в любом случае это, вероятно, всего лишь один другой скрипт, поэтому добавленный вес составляет всего 11 символов). Но это позволяет мне более точно контролировать, когда модуль инициализируется, и предлагает перехват для аргументов конфигурации, когда я (неизбежно) определю, что они мне понадобятся позже.
Комментарии:
1. Очень хороший ответ. Прямо сейчас я также возвращал функцию init(), но задавался вопросом, могу ли я сэкономить дополнительный шаг ее вызова на каждой странице. Ваши аргументы имеют идеальное значение!
2. Я действительно ценю ваш комментарий о том, что модуль ничего не делает при загрузке. Я пишу свой первый в истории настоящий модуль js, и мне было поручено использовать «раскрывающий модуль», в данном случае это скорее «скрывающий модуль», поскольку без an
init
ему действительно не нужно ничего раскрывать. Ваше предложениеinit
дало мне хороший старт.
Ответ №2:
Одинакова ли эта init()
функция на всех веб-страницах? Если да, то это то, что я бы сделал:
var foo = (function()
{
init();
return {};
}());
Если нет, я не вижу причин использовать IIFE и упростил бы ваш исходный код следующим образом:
var foo = (function()
{
/* body of the original IIFE here */
return {};
}());