Skip to content

Entendendo o ES6 Modules – Import e Export

Nesse post iremos entender como funciona o sistema de módulos do JavaScript, chamado ES6 modules.

Usando o ES6 modules para criar um módulo…

Quando estamos desenvolvendo uma aplicação em JavaScript, todos os módulos que implementamos ou utilizamos de terceiros, geralmente ficam em arquivos separados para que seja possível reutilizar em outros pontos da nossa aplicação.

Um módulo nada mais é do que um trecho de código responsável por realizar uma determinada função. Em um módulo podemos exportar variáveis, funções, classes e etc. Vejamos as possibilidades que temos para exportar um módulo usando o export do ES6 Modules:

1- export { modulo }
2- export { modulo, outroModulo, maisUmModulo }
3- export { modulo as aliasParaModulo }
4- export { modulo as default }
5- export default class|function
6- export { modulo, outroModulo } from 'moduloExterno'

Agora vamos entender cada um dos seis estados de export:

  1. Exporta de forma nomeada apenas um módulo. Pode ser uma variável, uma classe ou uma função.
  2. Exporta multiplos módulos nomeados em apenas uma declaração.
  3. Exporta um (ou mais) módulo, porém com um alias.
  4. Exporta um módulo e o define como default
  5. Exporta uma classe ou uma função definindo-as como default
  6. Exporta um ou mais módulos a partir de um submodulo externo.

Aqui eu listei apenas algumas possíveis formas de se fazer um export. É possível também, combiná-las conforme abaixo:

export { modulo, outroModulo as default, terceiroModulo as modulo3 }

Aqui combinamos praticamente todos anteriores em apenas um, exportando apenas um módulo nomeado, outro módulo como default e um terceiro com alias.

De uma forma resumida…

Primeiramente, vale ressaltar que todo o código escrito que compõe o módulo é executado em strict mode, ou seja, é executado de uma forma mais “rigorosa”, não deixando passar alguns erros que eram muito comuns em JavaScript e passavam despercebidos. Usar uma variável não declarada é um exemplo desse tipo de erro.

Com export, podemos exportar diversos módulos e pode ser usado em qualquer ponto do módulo, não necessáriamente no final do arquivo, como podemos observar abaixo:

export class {
    constructor(){}
    method() {}
}

Embora seja permitido usarmos o export em qualquer parte do nosso módulo, isso não vale para condicionais, ou seja, não podemos exportar com base no resultado de uma condicional:

if(true) {
    export default modulo; // Erro
}

E também não é permitido exportar o mesmo módulo ou alias mais de uma vez. Porém, é permitido exportar o mesmo módulo mais de uma vez mas com aliases diferentes.

export { modulo, modulo, modulo }  // Erro
export { modulo as modulo1, modulo as modulo2, modulo as modulo3 } // OK

Utilizando módulos com Import

Para importar um módulo, basta fazermos o caminho inverso do export, ou seja, usamos a instrução import. Sua sintaxe se da em duas partes: o modulo que queremos importar e o caminho do arquivo onde está localizado. Assim como no export, o import possui diversas formas de se trabalhar:

import modulo from 'arquivoDoModulo'
import { modulo } from 'arquivoDoModulo'
import { modulo as alias } from 'arquivoDoModulo'
import { modulo, outroModulo, terceiroModulo } from 'arquivoDoModulo'
import modulo, { outroModulo } from 'arquivoDoModulo'
import * as modulo from 'arquivoDoModulo'

Vamos entender cada uma dessas declarações de import:

  1. Importa o módulo definido como default no export e é nomeado como modulo.
  2. Faz o import nomeado de apenas um modulo
  3. Importa apenas o modulo e define um alias
  4. Importa três módulos
  5. Importa o modulo definido como default no export, e um outro modulo
  6. Importa todos os módulos exportados e define um alias modulo

Resumindo…

Assim como no export, não é permitido realizar import dentro de condicionais. Além disso, as variáveis importadas são de apenas leitura, ou seja, não podemos modificar seu valor fora do escopo do qual foi exportada.

Quando importamos um módulo, não estamos importando uma cópia do objeto exportado e sim disponibilizando o objeto exportado no escopo do código que o importa e, se fizermos um import e definirmos um alias, o módulo será referenciado pelo alias e não pelo export nomeado.

Diferença entre exports default e exports nomeados

Vejamos o seguinte exemplo:

export default (x, y) => x + y;

Nesse caso estamos exportando uma função anônima e definindo-a como default, ou seja, quando importarmos essa função em um outro ponto da aplicação, definiremos uma variável (soma) para referenciar esse módulo, pois nesse caso estamos importando seu namespace, conforme podemos ver no exemplo:

import soma from 'relativePath';

Se tivessemos outros módulos exportados, poderiamos importa-los também. Bastaria apenas separar por vírgula e envolve-los entre chaves. Veja o exemplo:

export default (x, y) => x + y;
const sub = (x, y) => x - y;

export sub;

E para importar:

import soma, { sub } from 'relativePath';

Eu não costumo usar ambos no mesmo módulo. Quando eu preciso exportar apenas um módulo, uso default. Quando preciso exportar vários, faço exports nomeados. Conforme você pode ver nos exemplos abaixo:

export default {
    sum = (x, y) => x + y,
    sub = (x, y) => x - y,
    mul = (x, y) => x * y,
    div = (x, y) => x / y     
}

Usando exports nomeados

const sum = (x, y) => x + y;
const sub = (x, y) => x - y;
const mul = (x, y) => x * y;
const div = (x, y) => x / y;

export { sum, sub, mul, div }

Bom, por enquanto é só! Até a próxima!

E se você gostou desse texto, passa pra frente e quem sabe pode ajudar outro dev 🙂

Published inJavaScriptNode.js

2 Comments

  1. Thiago Adriano Thiago Adriano

    muito boa a explicação parabéns 😉

    • raphaellima raphaellima

      Valeu, Thiago! 🙂

Comments are closed.