Módulos
Añadir manualmente todos los archivos de JavaScript que vamos a utilizar en nuestro HTML (clases, funciones, constantes, librerías, etc.) puede llegar a ser problemático en un proyecto grande y complejo. Podría generar problemas de sobreescritura de variables o funciones globales, incluir mucho más código del necesario en la aplicación, "ensuciar" el HTML, etc.
La división de nuestra aplicación en módulos (cada archivo es un módulo), soportada por JavaScript desde la versión ES2015, permite que en cada módulo podamos decidir que variables, funciones, clases, etc. exportaremos para usarlas desde otros módulos (archivos). De esta manera solo tenemos que incluir un (o pocos) archivo principal en el HTML y desde ahí importaremos el resto. Las variables serán locales siempre a cada módulo , reduciendo el riesgo de solapamiento de código, y los efectos colaterales que pueden tener variables y funciones globales a toda la aplicación.
Para utilizar módulos, solamente tenemos que declarar el script importado en html como type="module". Lo único malo de esto es que debemos ejecutar nuestra aplicación bajo un servidor web para que funcione.
Visual Studio Code tiene una extensión muy útil, Live Server, que permite ejecutar un servidor web ligero con un click de ratón (y pararlo de la misma manera).
Abajo a la derecha, verás una sección donde aparece "Go live". Con un solo click, se ejecutará el servicio, y se abrirá un navegador en http://localhost:5500 donde podrás probar la aplicación.
Para importar un archivo como JavaScript módulo en el HTML, añade el atributo type="module". No necesitarás ya el atributo defer, ya que estos scripts se ejecutan una vez procesado el HTML.
Cada archivo es un módulo, y en principio todo es privado (variables, constantes, clases, funciones) a dicho módulo (no accesible desde otros módulos). Para que otros módulos puedan usar por ejemplo, funciones o clases del módulo actual, debemos exportarlos.
La forma más simple sería un módulo que sólo exporta una cosa. Por ejemplo, un archivo donde sólo hay definida una clase y queremos utilizarla desde otros módulos. Usando la sintaxis export default exportamos el elemento en cuestión, que importamos desde otros módulos (podemos importarlo con cualquier nombre).
Si queremos exportar más de un elemento (o si queremos exportarlo con un nombre predefinido), no usaremos la palabra default, sino que lo que exportemos debe de tener un nombre. De esta manera podemos exportar varios elementos. Ahora al importar, debemos indicar qué elementos queremos importar del otro módulo entre llaves { }.
Otra manera de exportar elementos (equivalente a la anterior) es declarar al final del archivo lo que este exportará. Al igual que con el método anterior, no tenemos por qué importar todo lo que exporta un módulo desde otro, sólo lo que necesitamos.
También podemos asignar un alias a cualquier cosa que importemos con la palabra reservada as:
Otra opción es importar todo lo que un módulo exporta dentro de un objeto. Esto implica que para acceder a cualquier elemento importado (clase, constante, función), debemos acceder a él como una propiedad del objeto creado. Para ello creamos un alias (nombre del objeto) e importamos con esta sintaxis:
Por último, si queremos ejecutar un archivo JavaScript que no esté pensado como un módulo (una librería antigua por ejemplo), y que no exporta nada, simplemente importamos el archivo. En este caso, se ejecutará y procesará todo el contenido del archivo creando entre otras cosas las variables, funciones, etc. globales definidas en el mismo.