Linguagem avançada · unidade 17 de 27
Módulos ES
Módulos desenham as fronteiras do sistema.
01 / 07Use as setas do teclado ou deslize
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
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.
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.
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
- 01Implemente a função usando exatamente o nome e os parâmetros do enunciado.
- 02Salve sua implementação em
exercises.js, na mesma pasta do teste. - 03Abra o terminal nessa pasta e execute o comando abaixo.
- 04Se falhar, compare “esperado” com “recebido”; essa diferença mostra o caso que precisa ser corrigido.
node --test --test-name-pattern="createModule" exercises.test.jsComportamentos 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
function createModule(exportsObj) {
return Object.freeze({ ...exportsObj });
}