Skip to content

Integración de JavaScript en HTML ​

Para que JavaScript pueda proporcionar comportamiento a una página web, debemos integrar el código JavaScript con el documento HTML.

HTML proporciona el elemento <script> para incorporar o cargar código JavaScript.

Existen diferentes formas de hacerlo y la forma elegida puede afectar a la organización del proyecto y al momento en el que se ejecuta el código.

JavaScript dentro del documento HTML ​

Podemos escribir código JavaScript directamente dentro de un elemento <script>.

html
<!doctype html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>DWEC</title>
  </head>
  <body>
    <h1>DWEC</h1>

    <script>
      console.log("Hello DWEC");
    </script>
  </body>
</html>

En este caso, el código JavaScript forma parte del propio documento HTML.

Esta posibilidad puede resultar útil para ejemplos pequeños, pero dificulta la separación entre la estructura del documento y el comportamiento de la aplicación cuando el código aumenta.

JavaScript en un archivo externo ​

La forma habitual de organizar una aplicación consiste en almacenar el código JavaScript en uno o varios archivos independientes.

Por ejemplo:

text
project/
├── index.html
└── main.js

El archivo main.js podría contener:

js
console.log("Hello DWEC");

Desde HTML podemos cargarlo utilizando el atributo src del elemento <script>:

html
<script src="./main.js"></script>

Esta separación presenta diferentes ventajas:

  • Facilita la organización del proyecto.
  • Separa la estructura HTML del comportamiento JavaScript.
  • Facilita el mantenimiento del código.
  • Permite reutilizar archivos JavaScript.
  • Facilita el trabajo con aplicaciones de mayor tamaño.

TIP

En nuestros proyectos utilizaremos normalmente archivos JavaScript externos en lugar de escribir el código directamente dentro del documento HTML.

Posición del elemento script ​

El navegador procesa normalmente el documento HTML de arriba hacia abajo.

Por ello, la posición del elemento <script> puede influir en el momento en el que se descarga y ejecuta JavaScript.

Podemos encontrar un script dentro de <head>:

html
<head>
  <script src="./main.js"></script>
</head>

O cerca del final de <body>:

html
<body>
  <h1>DWEC</h1>

  <script src="./main.js"></script>
</body>

Cuando el navegador encuentra un <script> externo convencional durante el procesamiento del HTML, debe obtener y ejecutar el script antes de continuar procesando el documento.

De forma simplificada:

text
Procesar HTML
     │
     ↓
Encontrar <script>
     │
     ↓
Descargar JavaScript
     │
     ↓
Ejecutar JavaScript
     │
     ↓
Continuar procesando HTML

Esto puede provocar que el procesamiento del documento quede temporalmente bloqueado.

Situar el script al final de <body> ha sido tradicionalmente una forma sencilla de conseguir que gran parte del documento ya esté procesado cuando JavaScript comienza a ejecutarse.

El atributo defer ​

Otra posibilidad consiste en cargar el script desde <head> utilizando el atributo defer.

html
<head>
  <script src="./main.js" defer></script>
</head>

Con defer, el navegador puede descargar el archivo JavaScript mientras continúa procesando el documento HTML.

El script se ejecutará cuando el documento haya terminado de procesarse.

text
HTML       ──────────────────────────────>
              ↓
JavaScript    ───── descarga ─────>
                                   ↓
                                ejecución

Esto permite evitar que la descarga del script bloquee el procesamiento normal del HTML.

Además, cuando existen varios scripts con defer, se mantiene su orden relativo de ejecución.

html
<script src="./first.js" defer></script>
<script src="./second.js" defer></script>

first.js se ejecutará antes que second.js.

El atributo async ​

El atributo async también permite descargar un script mientras continúa procesándose el HTML.

html
<script src="./analytics.js" async></script>

Sin embargo, cuando termina la descarga, el script puede ejecutarse inmediatamente.

text
HTML       ────────────────┐       ─────────────>
                           │
JavaScript    ─ descarga ─>│ ejecución
                           │
                           └──────────────────────

Por ello, el momento de ejecución depende de cuándo finalice la descarga.

Si existen varios scripts con async, no se garantiza su orden de ejecución.

async resulta especialmente apropiado para scripts independientes que no dependen del documento ni de otros scripts.

Por ejemplo:

  • Scripts de analítica.
  • Determinados servicios externos.
  • Scripts independientes de terceros.

defer y async ​

Las principales diferencias pueden resumirse de la siguiente forma:

MecanismoDescargaEjecuciónMantiene el orden
<script> convencional.Puede bloquear el procesamiento del HTML.Inmediatamente al encontrarlo y disponer del archivo.Sí.
defer.En paralelo con el procesamiento del HTML.Después de procesar el documento.Sí.
async.En paralelo con el procesamiento del HTML.Cuando termina la descarga.No.

INFO

defer y async se utilizan con scripts externos.

Para el código JavaScript habitual de una aplicación que depende del documento HTML, defer ofrece un comportamiento predecible.

Módulos JavaScript ​

JavaScript moderno permite organizar una aplicación utilizando módulos.

Un archivo puede cargarse como módulo utilizando:

html
<script type="module" src="./main.js"></script>

Los módulos permiten dividir el código de una aplicación entre diferentes archivos y compartir elementos entre ellos mediante mecanismos como import y export.

Por ejemplo:

js
import { calculateTotal } from "./utils.js";

Los estudiaremos con mayor detalle cuando sean necesarios para estructurar aplicaciones más complejas.

INFO

Los scripts con type="module" tienen un comportamiento diferido de forma predeterminada, por lo que no es necesario añadir defer.

JavaScript directamente en elementos HTML ​

HTML también permite asociar código JavaScript directamente a determinados atributos.

Por ejemplo:

html
<button onclick="alert('Hello')">Click</button>

Este mecanismo mezcla la estructura HTML y el comportamiento JavaScript.

Aunque podemos encontrarlo en código existente y resulta válido técnicamente, en nuestros proyectos evitaremos utilizarlo.

Preferiremos mantener el comportamiento en archivos JavaScript:

html
<button id="helloButton">Click</button>
js
const button = document.querySelector("#helloButton");

button.addEventListener("click", () => {
  alert("Hello");
});

Separación de responsabilidades

Durante el módulo intentaremos mantener separadas las tres responsabilidades principales:

  • HTML: Estructura y contenido.
  • CSS: Presentación.
  • JavaScript: Comportamiento.

Esta separación facilita la organización, mantenimiento y evolución de las aplicaciones web.

Mecanismos de integración ​

Podemos resumir las principales formas de integrar JavaScript con HTML:

MecanismoEjemploUso
Script interno.<script>...</script>Ejemplos sencillos.
Script externo.<script src="./main.js"></script>Separación del código JavaScript.
Script con defer.<script src="./main.js" defer></script>Carga no bloqueante y ejecución tras procesar el HTML.
Script con async.<script src="./script.js" async></script>Scripts externos independientes.
Módulo.<script type="module" src="./main.js"></script>Aplicaciones JavaScript modulares.
Código en atributos HTML.onclick="..."Posible, pero evitaremos su uso.

En nuestros proyectos utilizaremos principalmente archivos JavaScript externos y módulos, manteniendo separado el comportamiento de la estructura HTML.