Linguagem avançada · unidade 17 de 27

Módulos ES

Módulos desenham as fronteiras do sistema.

7 min de leitura · 7 cards · 16 exercícios

Card 1 de 7: Módulos ES01 / 07

Leitura

Named exports, default, namespaces, reexports, cache de avaliação e dependências circulares.

No backend, esse fundamento aparece quando o código transforma entrada em decisão. O detalhe de linguagem deixa de ser acadêmico no momento em que altera um payload, uma regra de negócio ou a forma como uma falha chega à camada seguinte.

A forma mais útil de estudar é ligar a sintaxe a um contrato observável: o que entra, o que pode mudar, qual resultado sai e qual erro deve continuar o fluxo. É esse raciocínio que os exemplos e exercícios desta unidade procuram treinar.

Código

exemplo.js
export { parseOrder }
import { parseOrder } from "./orders.js"

O que fica

  • Imports tornam dependências explícitas.
  • Reexports devem revelar uma API, não esconder acoplamento.
  • Ciclos costumam apontar responsabilidades mal divididas.

Prática guiada.Leia, rode, quebre e explique cada exercício.

Prática guiada / unidade 17

Um problema de cada vez.

Leia o contrato, escreva sua tentativa e confira os casos esperados. A resolução de referência permanece visível ao final de cada exercício.

Fundamentalexercício 01 / 16

createModule(exportsObj)

01 / Entenda

Enunciado

recebe um objeto com os exports e retorna uma cópia congelada dele, simulando o objeto de módulo que o import recebe. Já implementado como exemplo.

02 / Implemente

Sua tentativa

Comece pela assinatura e resolva sem olhar a resposta.

ponto de partida
function createModule(exportsObj) {
  // Escreva sua solução aqui.
}

03 / Preveja

Entrada e saída

Use estes exemplos para entender o contrato antes de programar.

Entrada / chamada

createModule({ a: 1, b: 2 })

Retorno esperado

cria um objeto de módulo congelado (já implementado, exemplo)

04 / Teste

Prove que funciona

O teste chama sua função e compara o resultado real com o esperado.

Como utilizar este teste

  1. 01Implemente a função usando exatamente o nome e os parâmetros do enunciado.
  2. 02Salve sua implementação em exercises.js, na mesma pasta do teste.
  3. 03Abra o terminal nessa pasta e execute o comando abaixo.
  4. 04Se falhar, compare “esperado” com “recebido”; essa diferença mostra o caso que precisa ser corrigido.
node --test --test-name-pattern="createModule" exercises.test.js

Comportamentos cobertos

  • cria um objeto de módulo congelado (já implementado, exemplo)
  • Registry: define registra uma factory recuperável por nome
  • Registry: cada instância de registry tem seu próprio conjunto de módulos
Ver código completo do teste
test("createModule: cria um objeto de módulo congelado (já implementado, exemplo)", () => {
  const mod = createModule({ a: 1, b: 2 });
  assert.deepEqual(mod, { a: 1, b: 2 });
  assert.throws(() => {
    mod.a = 99;
  }, TypeError);
});

test("createModuleRegistry: define registra uma factory recuperável por nome", () => {
  const registry = createModuleRegistry();
  let calls = 0;
  registry.define("a", () => {
    calls += 1;
    return { value: 42 };
  });
  const entry = registry.modules.get("a");
  assert.equal(typeof entry.factory, "function");
  assert.deepEqual(entry.factory(), { value: 42 });
  assert.equal(calls, 1);
});

test("createModuleRegistry: cada instância de registry tem seu próprio conjunto de módulos", () => {
  const registryA = createModuleRegistry();
  const registryB = createModuleRegistry();
  registryA.define("a", () => "valor-a");
  assert.equal(registryB.modules.has("a"), false);
});

Ainda travou?

Dicas graduais

Nível 1 — direção, sem código

Para defineNamedExports/defineDefaultExport/mergeNamespaceImport: olhe como createModule já resolvido faz isso — Object.freeze em cima de uma cópia ({ ...obj }), nunca do objeto original.

Nível 1 — direção, sem código

Para createModuleRegistry: pense num Map como uma "prateleira" de módulos ainda não avaliados — define só guarda a receita (factory), não executa nada ainda.

Nível 2 — pista mais direta

createModuleRegistry:

return {
  modules: new Map(),
  define(name, factory) {
    this.modules.set(name, { factory });
  },
};

05 / Compare

Resolução

Esta área permanece livre em todos os exercícios. O código atual da unidade aparece abaixo para comparação com os testes e casos esperados.
código disponível
function createModule(exportsObj) {
  return Object.freeze({ ...exportsObj });
}