El concepto de módulos proviene del paradigma de programación modular. Este paradigma propone que el software debe estar compuesto de componentes separados e intercambiables llamados "módulos" al dividir las funciones del programa en archivos independientes que pueden funcionar por separado o acoplados en un solicitud.

Un módulo es un archivo independiente que encapsula código para implementar ciertas funciones y promover la reutilización y la organización.

Aquí cubrirá los sistemas de módulos utilizados en las aplicaciones de JavaScript, incluido el patrón de módulo, el sistema de módulos CommonJS utilizado en la mayoría de las aplicaciones de Node.js y el sistema de módulos ES6.

El patrón del módulo

Antes de la introducción de los módulos nativos de JavaScript, el patrón de diseño de módulos se usaba como un sistema de módulos para abarcar variables y funciones en un solo archivo.

Esto se implementó utilizando expresiones de función invocadas inmediatamente, conocidas popularmente como IIFE. Un IIFE es una función no reutilizable que se ejecuta tan pronto como se crea.

instagram viewer

Aquí está la estructura básica de un IIFE:

(función () {
// código aquí
})();

(() => {
// código aquí
})();

(asíncrono () => {
// código aquí
})();

El bloque de código anterior describe los IIFE utilizados en tres contextos diferentes.

Se usaron IIFE porque las variables declaradas dentro de una función tienen el alcance de la función, lo que las hace solo accesible dentro de la función, y porque las funciones le permiten devolver datos (haciéndolos públicamente accesible).

Por ejemplo:

constante fo = (función () {
constante decirNombre = (nombre) => {
consola.registro(`Oye, mi nombre es ${nombre}`);
};
//Exponiendo las variables
devolver {
callSayName: (nombre) => decirNombre (nombre),
};
})();
//Accediendo a los métodos expuestos
foo.callSayName("Bar");

El bloque de código anterior es un ejemplo de cómo se crearon los módulos antes de la introducción de los módulos JavaScript nativos.

El bloque de código anterior contiene un IIFE. El IIFE contiene una función que hace accesible devolviéndola. Todas las variables declaradas en el IIFE están protegidas del ámbito global. Así, el método (decirNombre) solo es accesible a través de la función pública, llamarDigaNombre.

Observe que el IIFE se guarda en una variable, Foo. Esto se debe a que, sin una variable que apunte a su ubicación en la memoria, las variables serán inaccesibles después de que se ejecute el script. Este patrón es posible debido a Cierres de JavaScript.

El sistema de módulos CommonJS

El sistema de módulos CommonJS es un formato de módulo definido por el grupo CommonJS para resolver problemas de alcance de JavaScript mediante la ejecución de cada módulo en su espacio de nombres.

El sistema de módulos CommonJS funciona al obligar a los módulos a exportar explícitamente las variables que desean exponer a otros módulos.

Este sistema de módulos fue creado para JavaScript del lado del servidor (Node.js) y, como tal, no se admite de forma predeterminada en los navegadores.

Para implementar módulos CommonJS en su proyecto, primero debe inicializar NPM en su aplicación ejecutando:

npm inicializar -y

Las variables exportadas siguiendo el sistema de módulos CommonJS se pueden importar así:

//randomModule.js
//paquete instalado
constante Importación instalada = requerir("Nombre del paquete");
//módulo local
constante importación local = requerir("/path-to-module");

Los módulos se importan en CommonJS usando el requerir instrucción, que lee un archivo JavaScript, ejecuta el archivo leído y devuelve el exportaciones objeto. El exportaciones El objeto contiene todas las exportaciones disponibles en el módulo.

Puede exportar una variable siguiendo el sistema de módulos CommonJS utilizando exportaciones con nombre o exportaciones predeterminadas.

Exportaciones con nombre

Las exportaciones con nombre son exportaciones identificadas por los nombres que se les asignaron. Las exportaciones con nombre permiten múltiples exportaciones por módulo, a diferencia de las exportaciones predeterminadas.

Por ejemplo:

//main.js
exportaciones.miexportación = función () {
consola.log("Este es un ejemplo de un nombre exportar");
};
exportaciones.otraexportación = función () {
consola.log("Este es otro ejemplo de un nombre exportar");
};

En el bloque de código anterior, está exportando dos funciones con nombre (miexportación y otroExportar) uniéndolos a la exportaciones objeto.

Del mismo modo, puede exportar las funciones de esta manera:

constante miexportación = función () {
consola.log("Este es un ejemplo de un nombre exportar");
};
constante otraexportación = función () {
consola.log("Este es otro ejemplo de un nombre exportar");
};
módulo.exportaciones = {
miexportación,
otra exportación,
};

En el bloque de código anterior, establece el exportaciones objeto a las funciones nombradas. Sólo puede asignar el exportaciones objeto a un nuevo objeto a través de la módulo objeto.

Su código arrojaría un error si intentara hacerlo de esta manera:

//Camino equivocado
exportaciones = {
miexportación,
otra exportación,
};

Hay dos formas de importar exportaciones con nombre:

1. Importe todas las exportaciones como un solo objeto y acceda a ellas por separado usando la notación de punto.

Por ejemplo:

//otherModule.js
constante foo = requerir("./principal");
Foo.miexportación();
Foo.otraexportación();

2. Desestructurar las exportaciones del exportaciones objeto.

Por ejemplo:

//otherModule.js
constante { miExportación, otraExportación } = requerir("./principal");
miexportación();
otraExportación();

Una cosa es común en todos los métodos de importación, se deben importar con los mismos nombres con los que se exportaron.

Exportaciones predeterminadas

Una exportación predeterminada es una exportación identificada con cualquier nombre de su elección. Solo puede tener una exportación predeterminada por módulo.

Por ejemplo:

//main.js
claseFoo{
bar() {
consola.log("Este es un ejemplo de a por defectoexportar");
}
}
módulo.exportaciones = Fu;

En el bloque de código anterior, está exportando una clase (Foo) reasignando el exportaciones objetarlo.

La importación de exportaciones predeterminadas es similar a la importación de exportaciones con nombre, excepto que puede usar cualquier nombre de su elección para importarlas.

Por ejemplo:

//otherModule.js
constante barra = requerir("./principal");
constante objeto = nuevo Bar();
objeto.bar();

En el bloque de código anterior, la exportación predeterminada se nombró Bar, aunque puede utilizar cualquier nombre de su elección.

El sistema de módulos ES6

El sistema de módulos ECMAScript Harmony, conocido popularmente como módulos ES6, es el sistema de módulos oficial de JavaScript.

Los módulos ES6 son compatibles con navegadores y servidores, aunque requiere un poco de configuración antes de usarlos.

En los navegadores, debe especificar el tipo como módulo en la etiqueta de importación del script.

Al igual que:

//index.html
<secuencia de comandos src="./app.js" tipo ="módulo"></script>

En Node.js, debe configurar tipo a módulo en tus paquete.json archivo.

Al igual que:

//package.json
"tipo":"módulo"

También puede exportar variables utilizando el sistema de módulos ES6 mediante exportaciones con nombre o exportaciones predeterminadas.

Exportaciones con nombre

Al igual que las importaciones con nombre en los módulos de CommonJS, se identifican por los nombres que se les asignaron y permiten múltiples exportaciones por módulo.

Por ejemplo:

//main.js
exportarconstante miexportación = función () {
consola.log("Este es un ejemplo de un nombre exportar");
};
exportarconstante otraexportación = función () {
consola.log("Este es otro ejemplo de un nombre exportar");
};

En el sistema de módulos ES6, las exportaciones con nombre se exportan prefijando la variable con el exportar palabra clave.

Las exportaciones con nombre se pueden importar a otro módulo en ES6 de la misma manera que CommonJS:

  • La desestructuración de las exportaciones requeridas del exportaciones objeto.
  • Importando todas las exportaciones como un solo objeto y accediendo a ellas por separado usando la notación de puntos.

He aquí un ejemplo de desestructuración:

//otherModule.js
importar { miExportación, otraExportación } de "./principal.js";
miexportación()
otraExportación()

Aquí hay un ejemplo de importar el objeto completo:

importar * como Foo de './principal.js'
Foo.miexportación()
Foo.otraexportación()

En el bloque de código anterior, el asterisco (*) significa “todos”. El como palabra clave asigna la exportaciones objeto a la cadena que le sigue, en este caso, Foo.

Exportaciones predeterminadas

Al igual que las exportaciones predeterminadas en CommonJS, se identifican con cualquier nombre que elija y solo puede tener una exportación predeterminada por módulo.

Por ejemplo:

//main.js
claseFoo{
bar() {
consola.log("Este es un ejemplo de a por defectoexportar");
}
}
exportarpor defecto Fu;

Las exportaciones predeterminadas se crean agregando el por defecto palabra clave después de la exportar palabra clave, seguida del nombre de la exportación.

La importación de exportaciones predeterminadas es similar a la importación de exportaciones con nombre, excepto que puede usar cualquier nombre de su elección para importarlas.

Por ejemplo:

//otherModule.js
importar Bar de "./principal.js";

Exportaciones Mixtas

El estándar del módulo ES6 le permite tener exportaciones predeterminadas y exportaciones con nombre en un módulo, a diferencia de CommonJS.

Por ejemplo:

//main.js
exportarconstante miexportación = función () {
consola.log("Este es otro ejemplo de un nombre exportar");
};
claseFoo{
bar() {
consola.log("Este es un ejemplo de a por defectoexportar");
}
}
exportarpor defecto Fu;

Importancia de los módulos

Dividir su código en módulos no solo los hace más fáciles de leer, sino que también lo hace más reutilizable y fácil de mantener. Los módulos en JavaScript también hacen que su código sea menos propenso a errores, ya que todos los módulos se ejecutan en modo estricto de forma predeterminada.