Использование самозапускающихся анонимных функций внутри шаблона раскрывающегося модуля - PullRequest
2 голосов
/ 04 октября 2011

Просто хотел узнать, была ли это хорошая практика 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
    }
}());

Ответы [ 2 ]

6 голосов
/ 04 октября 2011

Это довольно субъективная область, но вот мое мнение:

  • Когда вы используете шаблон модуля, вы предоставляете набор функций для остальной части вашего кода. По сути, это мини-библиотека.

  • В общем, я бы не ожидал, что библиотека сделает что-либо при загрузке, кроме шагов инициализации, которые являются полностью внутренними для библиотеки (например, настройка настройка конфигурации, создание нескольких необходимых объектов и т. д.) - ничего, что действительно влияет на DOM или иным образом существенно меняет среду (вот почему мне никогда не было так удобно с такими библиотеками, как Date.js или Prototype, которые изменяют прототипы basic объекты).

  • Для этого есть несколько причин, но главная из них заключается в том, что мне не нужно беспокоиться о порядке загрузки моих библиотек / модулей, кроме простого управления зависимостями. Независимые модули не должны влиять друг на друга вообще . Когда вы манипулируете 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 голос
/ 04 октября 2011

Функция init() одинакова для всех веб-страниц? Если так, то вот что я бы сделал:

var foo = (function()
{
    init();
    return {};
}());

Если нет, я не вижу причин использовать IIFE, и упростил бы ваш исходный код следующим образом:

var foo = (function()
{
    /* body of the original IIFE here */
    return {};
}());
...