preloader

Export e Import en JavaScript

Las directivas export e import tienen diversas variantes en su sintaxis.

En el artículo anterior vimos un uso sencillo, ahora exploraremos más ejemplos.

Exportación previa a las declaraciones

Podemos marcar cualquier declaración como exportada colocando export antes, ya sea una variable, una función o una clase.

Por ejemplo, todas las exportaciones siguientes son válidas:

				
					// exportar un array
export let months = ['Jan', 'Feb', 'Mar', 'Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

// exportar una constante
export const MODULES_BECAME_STANDARD_YEAR = 2015;

// exportar una clase
export class User {
  constructor(name) {
    this.name = name;
  }
}

				
			

Sin punto y coma después de export class o export function

Es importante tener en cuenta que export antes de una clase o función no la convierte en una expresión de función. Sigue siendo una declaración de función, aunque exportada.

La mayoría de las guías de estilo de JavaScript no recomiendan el uso de punto y coma después de declarar funciones y clases.

Por esta razón, no es necesario un punto y coma al final de export class o export function:

				
					export function sayHi(user) {
  alert(`Hello, ${user}!`);
}  // no ; al final

				
			

Exportación separada de la declaración

También podemos colocar export por separado.

Aquí primero declaramos y luego exportamos:

				
					// 📁 say.js
function sayHi(user) {
  alert(`Hello, ${user}!`);
}

function sayBye(user) {
  alert(`Bye, ${user}!`);
}

export {sayHi, sayBye}; // una lista de variables exportadas

				
			

Importar todo

Generalmente, listamos lo que queremos importar entre llaves import {...}, de esta manera:

				
					// 📁 main.js
import {sayHi, sayBye} from './say.js';

sayHi('John'); // Hello, John!
sayBye('John'); // Bye, John!

				
			

Pero si hay mucho para importar, podemos importar todo como un objeto utilizando import * as <obj>, por ejemplo:

				
					// 📁 main.js
import * as say from './say.js';

say.sayHi('John');
say.sayBye('John');

				
			

Importar con alias

También podemos usar as para importar con nombres diferentes.

Por ejemplo, importemos sayHi en la variable local hi para brevedad, e importemos sayBye como bye:

				
					// 📁 main.js
import {sayHi as hi, sayBye as bye} from './say.js';

hi('John'); // Hello, John!
bye('John'); // Bye, John!

				
			

Exportar con alias

Existe una sintaxis similar para exportar.

Exportemos funciones como hi y bye:

				
					// 📁 say.js
export {sayHi as hi, sayBye as bye};

				
			

Ahora hi y bye son los nombres oficiales para ser utilizados en importaciones:

				
					// 📁 main.js
import * as say from './say.js';

say.hi('John'); // Hello, John!
say.bye('John'); // Bye, John!

				
			

Exportación predeterminada

En la práctica, existen principalmente dos tipos de módulos:

  1. Módulos que contienen una librería, paquete de funciones, como say.js de arriba.
  2. Módulos que declaran una entidad simple, por ejemplo, un módulo user.js que exporta únicamente class User.

Principalmente, se prefiere el segundo enfoque, de modo que cada «cosa» reside en su propio módulo.

Naturalmente, eso requiere muchos archivos, ya que todo quiere su propio módulo, pero eso no es un problema en absoluto. En realidad, la navegación de código se vuelve más fácil si los archivos están bien nombrados y estructurados en carpetas.

Los módulos proporcionan una sintaxis especial export default («la exportación predeterminada») para que la forma de «una cosa por módulo» se vea mejor.

Poner export default antes de la entidad a exportar:

				
					// 📁 user.js
export default class User { // solo agregar "default"
  constructor(name) {
    this.name = name;
  }
}

				
			

Solo puede existir una sola exportación predeterminada por archivo.

…Y luego importarlo sin llaves:

				
					// 📁 main.js
import User from './user.js'; // no {User}, solo User

new User('John');

				
			

Las importaciones sin llaves se ven mejor. Un error común al comenzar a usar módulos es olvidarse de las llaves. Entonces, recuerde, import necesita llaves para las exportaciones con nombre y no las necesita para la predeterminada.

Resumen

Aquí están todos los tipos de ‘exportación’ que cubrimos en este y en artículos anteriores:

  • Antes de la declaración de clase/función/variable:
				
					export [default] class/function/variable ...

				
			
  • Exportación independiente:
				
					export {x [as y], ...}.

				
			
  • Reexportar:
				
					export {x [as y], ...} from "module"
export * from "module" (no reexporta la predeterminada).
export {default [as y]} from "module" (reexporta la predeterminada).

				
			

Importación

  • Importar exportaciones con nombre:
				
					import {x [as y], ...} from "module"

				
			
  • Importar la exportación predeterminada:
				
					import x from "module"
import {default as x} from "module"

				
			
  • Importar todo:
				
					import * as obj from "module"

				
			
  • Importar el módulo (su código se ejecuta), pero no asigna ninguna de las exportaciones a variables:
				
					import "module"

				
			

Podemos poner las declaraciones import/export en la parte superior o inferior de un script, eso no importa.

Entonces, técnicamente este código está bien:

				
					sayHi();

// ...

import {sayHi} from './say.js'; // import al final del archivo

				
			

En la práctica, las importaciones generalmente se encuentran al comienzo del archivo, pero eso es solo para mayor comodidad.

Importación condicional

Las declaraciones de import/export no funcionan si están dentro de un bloque {...}.

Una importación condicional, como esta, no funcionará:

				
					if (something) {
  import {sayHi} from "./say.js"; // Error: import debe estar en nivel superior
}

				
			

…Pero, ¿qué pasa si realmente necesitamos importar algo condicionalmente? O en el momento adecuado? Por ejemplo, ¿cargar un módulo a pedido, cuando realmente se necesita?

Veremos importaciones dinámicas en el próximo artículo.

Related Post

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *