Padrão de módulo JavaScript com exemplo [fechado]


136

Não consigo encontrar exemplos acessíveis que mostrem como dois (ou mais) módulos diferentes estão conectados para trabalhar juntos.

Então, eu gostaria de perguntar se alguém tem tempo para escrever um exemplo explicando como os módulos funcionam juntos.


Tudo mudou nos últimos quatro anos, mas graças à zelo em excesso de moderação, essas informações desatualizadas permanecerão para sempre . Aqui está a página da MDN nos módulos ES6.
precisa saber é o seguinte

Respostas:


256

Para abordar o padrão de design modular, você precisa entender estes conceitos primeiro:

Expressão de Função Imediatamente Invocada (IIFE):

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

Existem duas maneiras de usar as funções. 1. Declaração de função 2. Expressão de função.

Aqui estão usando a expressão de função.

O que é espaço para nome? Agora, se adicionarmos o espaço para nome ao trecho de código acima,

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

O que é fechamento em JS?

Isso significa que, se declararmos qualquer função com qualquer escopo variável / dentro de outra função (em JS, podemos declarar uma função dentro de outra função!), Ele sempre contará esse escopo da função. Isso significa que qualquer variável na função externa será lida sempre. Não lerá a variável global (se houver) com o mesmo nome. Esse também é um dos objetivos do uso de padrão de design modular, evitando conflitos de nomes.

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

Agora, aplicaremos esses três conceitos mencionados acima para definir nosso primeiro padrão de design modular:

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 para o código acima.

O objetivo é ocultar a acessibilidade variável do mundo exterior.

Espero que isto ajude. Boa sorte.


seria melhor nomear a vida? para fins semânticos e melhor rastreamento de pilha? isso mudaria alguma coisa no código?
Jeroen

2
Seu primeiro exemplo (function() { /* Your code goes here */}());é, na verdade, uma IIFE (expressão de função de chamada imediata), ok, é anônima porque não tem nome; portanto, você pode até chamá-la de IIAFE (expressão de função de descrição anônima de chamada imediata). Veja mais sobre IIFE em stackoverflow.com/questions/ 2421911 /…
Adrien Seja

por que a declaração de retorno foi usada? se omitir return {}, a função add e reset seria public e eu acho que eles podem acessar a soma da variável local? Estou certo?
Mou

seu segundo exemplo parece um objeto ou não estou certo?
A razão

4
Isso não aborda a questão do OP. É uma descrição do padrão do módulo, não um exemplo de como vários módulos podem trabalhar juntos como o OP desejava.
Erik Trautman

39

Eu realmente recomendaria que qualquer pessoa que entra neste assunto leia o livro gratuito de Addy Osmani:

"Aprendendo padrões de design JavaScript".

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

Este livro me ajudou imensamente quando eu comecei a escrever JavaScript mais sustentável e ainda o uso como referência. Dê uma olhada em suas diferentes implementações de padrões de módulos, ele as explica muito bem.


Eu também recomendo ler o meu artigo sobre o "Padrão Módulo definitivo", que não é coberto no livro de Addy Osmani: github.com/tfmontague/definitive-module-pattern
tfmontague

1
Como isso se compara aos "JavaScript Patterns" de Stoyan Stefanov
JohnMerlino 18/08/14

4
O livro de Stoyan é muito mais abrangente. Ele abrange mais do que apenas padrões de alto nível, mas também fala mais profundamente sobre outras práticas recomendadas de JS.
Código Noviciado

1
avaliações de "Aprendendo padrões de design do JavaScript" amazon.com/product-reviews/1449331815
Adrien Seja

3
avaliações de "JavaScript Patterns" de Stoyan Stefanov amazon.com/product-reviews/0596806752 . Nota: que parece muito melhor do que o de "Aprendendo padrões de design do JavaScript"
Adrien Seja

19

Eu pensei em expandir a resposta acima falando sobre como você encaixaria os módulos em um aplicativo. Eu tinha lido sobre isso no livro de Doug Crockford, mas sendo novo no javascript ainda era um pouco misterioso.

Eu venho do fundo ac #, então adicionei alguma terminologia que acho útil a partir daí.

Html

Você terá algum tipo de arquivo html de nível superior. Ajuda pensar nisso como seu arquivo de projeto. Todo arquivo javascript que você adiciona ao projeto quer entrar nisso, infelizmente você não recebe suporte de ferramenta para isso (estou usando o IDEA).

Você precisa adicionar arquivos ao projeto com tags de script como estas:

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

Parece que o colapso das tags faz com que as coisas falhem - enquanto parece que o xml é realmente algo com regras mais loucas!

Arquivo de espaço para nome

MasterFile.js

myAppNamespace = {};

é isso aí. Isso é apenas para adicionar uma única variável global para o restante do nosso código. Você também pode declarar namespaces aninhados aqui (ou em seus próprios arquivos).

Módulo (s)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

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

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

O que estamos fazendo aqui é atribuir uma função de contador de mensagens a uma variável em nosso aplicativo. É uma função que retorna uma função que executamos imediatamente .

Conceitos

Eu acho que ajuda pensar na linha superior em SomeComponent como sendo o espaço para nome em que você está declarando algo. A única ressalva é que todos os seus namespaces precisam aparecer em algum outro arquivo primeiro - eles são apenas objetos enraizados na nossa variável de aplicativo.

No momento, apenas tomei pequenas medidas com isso (estou refatorando algum javascript normal de um aplicativo extjs para que eu possa testá-lo), mas parece muito bom, pois você pode definir pequenas unidades funcionais e evitar o atoleiro 'this ' .

Você também pode usar esse estilo para definir construtores retornando uma função que retorna um objeto com uma coleção de funções e não chamando imediatamente.


6

Aqui https://toddmotto.com/mastering-the-module-pattern, você pode encontrar o padrão completamente explicado. Eu acrescentaria que a segunda coisa sobre o JavaScript modular é como estruturar seu código em vários arquivos. Muitas pessoas podem aconselhá-lo aqui a usar a AMD, mas posso dizer por experiência própria que você acabará em algum momento com uma resposta lenta da página devido a inúmeras solicitações HTTP. A saída é a pré-compilação de seus módulos JavaScript (um por arquivo) em um único arquivo, seguindo o padrão CommonJS. Dê uma olhada nas amostras aqui http://dsheiko.github.io/cjsc/


Todas as implementações da AMD também fornecem pré-compilação em um único arquivo.
I-Lin Kuo

1
Isso está correto, mas o arquivo otimizado resultante requer a biblioteca do carregador (apenas a verifique novamente com r.js v2.1.14), que geralmente é bastante pesada. Assim que compilamos o código, não precisamos resolver dependências carregadas de forma assíncrona, não precisamos dessa biblioteca. Basta considerar: envolvemos os módulos na AMD, o que significa assíncrono. carregando, compile-os em um único arquivo (não há mais carregamento separado), mas carregue a biblioteca inteira para resolvê-los (o que é redundante agora). Não parece uma maneira ideal para mim. Por que AMD quando não carregamos de forma assíncrona?
Dmitry Sheiko

O almond.js fornece um carregador de peso menor para o código de produção final do que o RequireJS, mas comparativamente, o benefício de desempenho de não fazer apenas uma única solicitação http supera em muito o custo de adicionar o código do carregador ao módulo, portanto, embora seja menos ideal, é em uma escala muito menor. A questão, na minha opinião, deve ser revertida - por que assumir a sincronicidade quando o navegador não está? Na verdade eu sou da opinião de que ambos os RequireJS e commonjs deve ter uma implementação promessa construído dentro.
I-Lin Kuo

Ambos os formatos são caminhos válidos para o CommonJS Modules / 2.0 e fornecem a mesma escalabilidade. Quanto a mim - lidar com CJS Modules / 1.1 (é o que quero dizer com CommonJS) é muito mais fácil, o código parece mais limpo.
Dmitry Sheiko

Conheci os benefícios da AMD como: * pode carregar mais do que apenas arquivos JavaScript; * aliases de caminho; Bem, o CommonJS Compiler resolve isso - ele carrega dependências não JavaScipt / JSON como dados e pode ser fornecido com a configuração de construção (incluindo aliases). A única desvantagem que requer construção. Mas hoje em dia todo mundo constrói o projeto para pré-processadores CSS. Por isso, é apenas sobre a adição de uma tarefa extra para Grunt / Gulp ...
Dmitry Sheiko

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.