Шаблон модуля JavaScript с примером [закрыто]

136

Я не могу найти доступных примеров, показывающих, как два (или более) разных модуля соединены для совместной работы.

Итак, я хотел бы спросить, есть ли у кого-нибудь время написать пример, объясняющий, как модули работают вместе.

Srle
источник
Все это изменилось за последние четыре года, но благодаря усердной чрезмерной модерации эта устаревшая информация будет храниться вечно . Вот страница MDN по модулям ES6.
bbsimonbb

Ответы:

256

Для того, чтобы приблизиться к шаблону модульного дизайна, вы должны сначала понять эти концепции:

Выражение с немедленным вызовом функции (IIFE):

(function() {
      // Your code goes here 
}());

Есть два способа использования функций. 1. Объявление функции 2. Выражение функции.

Здесь используются функции выражения.

Что такое пространство имен? Теперь, если мы добавим пространство имен в приведенный выше фрагмент кода, то

var anoyn = (function() {
}());

Что такое закрытие в JS?

Это означает, что если мы объявим какую-либо функцию с любой переменной scope / внутри другой функции (в JS мы можем объявить функцию внутри другой функции!), То она всегда будет считать эту область действия. Это означает, что любая переменная во внешней функции будет читаться всегда. Он не будет читать глобальную переменную (если таковая имеется) с тем же именем. Это также одна из целей использования шаблона модульного проектирования, позволяющего избежать конфликта имен.

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

Теперь мы применим эти три понятия, которые я упомянул выше, чтобы определить наш первый шаблон модульного дизайна:

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

jsfiddle для кода выше.

Цель состоит в том, чтобы скрыть переменную доступность от внешнего мира.

Надеюсь это поможет. Удачи.

КТА
источник
было бы лучше назвать IIFE? для семантических целей и лучшего отслеживания стека? это что-то изменит в коде?
Йерун
2
Ваш первый пример (function() { /* Your code goes here */}());на самом деле - IIFE (выражение немедленного вызова функции), хорошо, это анонимно, потому что у него нет имени, так что вы можете даже назвать его IIAFE (выражение немедленного вызова анонимной функции), подробнее о IIFE см. На stackoverflow.com/questions/ 2421911 /…
Adrien Be
почему выражение return было использовано? если мы опускаем return {}, тогда функция добавления и сброса будет публичной, и я думаю, они могут получить доступ к локальной переменной sum? я прав?
Моу
Ваш второй пример выглядит как объект или я не прав?
Причина
4
Это не относится к вопросу ОП. Это описание шаблона модуля, а не пример того, как несколько модулей могут работать вместе, как того хотел ОП.
Эрик Траутман
39

Я очень рекомендую всем, кто входит в эту тему, прочитать бесплатную книгу Адди Османи:

«Изучение шаблонов дизайна JavaScript».

http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Эта книга очень помогла мне, когда я начал писать более понятный JavaScript, и я все еще использую его как справочник. Взгляните на его различные реализации шаблонов модулей, он очень хорошо их объясняет.

Код Новициат
источник
Я также рекомендовал бы прочитать мою статью о «
Шаблоне
1
Как это соотносится с «
Шаблонами
4
Книга Стояна гораздо более полная. Он охватывает не только шаблоны высокого уровня, но и более подробно рассказывает о других лучших практиках JS.
Код Novitiate
1
обзоры «Изучение шаблонов дизайна JavaScript» amazon.com/product-reviews/1449331815
Адриен Бе
3
Отзывы о «Паттернах JavaScript» Стояна Стефанова amazon.com/product-reviews/0596806752 . Примечание: которые кажутся намного лучше, чем в «Изучении шаблонов проектирования JavaScript»
Adrien Be
19

Я подумал, что я бы расширил приведенный выше ответ, поговорив о том, как вы поместите модули вместе в приложение. Я читал об этом в книге Дуга Крокфорда, но, будучи новичком в javascript, все это было немного загадочно.

Я пришел из ac # background, поэтому добавил терминологию, которая мне там пригодится.

Html

У вас будет какой-то HTML-файл верхнего уровня. Это помогает думать об этом как о файле вашего проекта. Каждый javascript-файл, который вы добавляете в проект, хочет в него войти, к сожалению, вы не получаете поддержку инструмента (я использую IDEA).

Вам нужно добавить файлы в проект с помощью тегов скриптов, например:

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

Похоже, что свертывание тегов приводит к ошибкам - хотя это выглядит как xml, это действительно нечто с безумными правилами!

Файл пространства имен

MasterFile.js

myAppNamespace = {};

Это оно. Это просто для добавления одной глобальной переменной для остальной части нашего кода, чтобы жить. Вы также можете объявить вложенные пространства имен здесь (или в их собственных файлах).

Модуль (ы)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

Здесь мы назначаем функцию счетчика сообщений переменной в нашем приложении. Это функция, которая возвращает функцию, которую мы немедленно выполняем .

Концепции

Я думаю, что это помогает думать о верхней строке в SomeComponent как о пространстве имен, в котором вы что-то объявляете. Единственное предостережение: все ваши пространства имен должны сначала появиться в каком-то другом файле - это просто объекты, укорененные нашей переменной приложения.

На данный момент я предпринял лишь незначительные шаги с этим (я рефакторинг некоторого нормального javascript из приложения extjs, чтобы я мог его протестировать), но это довольно неплохо, так как вы можете определить небольшие функциональные блоки, избегая при этом болота 'this ' .

Вы также можете использовать этот стиль для определения конструкторов, возвращая функцию, которая возвращает объект с набором функций, и не вызывая его немедленно.

JonnyRaa
источник
6

Здесь https://toddmotto.com/mastering-the-module-pattern вы можете найти шаблон, подробно объясненный. Я бы добавил, что вторая вещь о модульном JavaScript - это то, как структурировать ваш код в несколько файлов. Многие люди могут посоветовать вам перейти на AMD, но по опыту могу сказать, что в какой-то момент вы столкнетесь с медленным откликом страницы из-за многочисленных HTTP-запросов. Выходом является предварительная компиляция ваших модулей JavaScript (по одному на файл) в один файл в соответствии со стандартом CommonJS. Посмотрите образцы здесь http://dsheiko.github.io/cjsc/

Дмитрий Шейко
источник
Все реализации AMD также обеспечивают прекомпиляцию в один файл.
И-Лин Куо,
1
Это правильно, но полученный оптимизированный файл требует библиотеку загрузчика (только что проверил ее с помощью r.js v2.1.14), что обычно довольно тяжело. Как только мы скомпилировали код, нам не нужно разрешать асинхронно загруженные зависимости, нам не нужна эта библиотека. Просто подумайте: мы упаковываем модули в AMD, что означает асинхронность. загрузка, затем скомпилируйте их в один файл (больше не нужно загружать отдельно), но загрузите всю библиотеку для их решения (что теперь является излишним). Это не звучит как оптимальный способ для меня. Почему AMD вообще, когда мы не загружаем асинхронно?
Дмитрий Шейко
almond.js обеспечивает меньший весовой коэффициент загрузки готового производственного кода, чем RequireJS, но, сравнительно говоря, выигрыш в производительности, заключающийся в том, что выполнение не одного простого http-запроса значительно превышает стоимость добавления кода загрузчика в модуль, поэтому, хотя он менее оптимален, он в гораздо меньшем масштабе. Вопрос, на мой взгляд, должен быть перевернут - зачем предполагать синхронность, а браузер - нет? Я на самом деле считаю, что и RequireJS, и CommonJS должны иметь встроенную реализацию обещания.
I-Lin Kuo
Оба формата являются допустимыми путями к CommonJS Modules / 2.0 и обеспечивают одинаковую масштабируемость. Что касается меня - работать с CJS Modules / 1.1 (это то, что я имею в виду под CommonJS) гораздо проще, код выглядит чище.
Дмитрий Шейко
Я встречал такие преимущества AMD, как: * может загружать не только файлы JavaScript; * псевдонимы пути; Что ж, CommonJS Compiler решает их - он загружает не-JavaScipt / JSON-зависимости как данные и может быть предоставлен с конфигурацией сборки (включая псевдонимы). Единственный недостаток, который требует строительства. Но в настоящее время каждый в любом случае создает проект для препроцессоров CSS. Так что речь идет только о добавлении дополнительного задания для Grunt / Gulp ...
Дмитрий Шейко