¿Por qué es recomendable usar el <script> en el <head>?

Me gustaría saber por que es recomendable trabajar el Javascript en el <head>, pues hasta donde tengo entendido en la mayoría de las partes se recomienda trabajarlo antes de cerrar el <body>, esto para permitir que se cargue tranquilamente el HTML, a continuación cito dos ejemplos para ver la diferencia entre los dos tipos de carga de JavaScript.

Ejemplo JavaScript en el <head>:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Javascript head</title>
    <script>
      alert("El body todavía no existe!!")
    </script>
  </head>
  <body>
    <h1>Soy un título</h1>
    <p>Hola yo soy un párrafo</p>
  </body>
</html>

Ejemplo JavaScript en el <body>:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Javascript al final del body</title>
  </head>
  <body>
    <h1>Soy un título</h1>
    <p>Hola yo soy un párrafo</p>
 
    <script>
      alert("El body esta listo y lo puedes ver en el fondo!!")
    </script>
  </body>
</html>

Me gustaría saber qué ventajas tiene trabajarlo en el <head>, por favor no dejarnos con la información a media?

¡Muchas gracias!

PD: Muy buena su página felicitaciones.

Respuestas

#1

El mejor lugar para incluir o enlazar el código JavaScript depende tanto del propio código JavaScript como de la aplicación o sitio web que lo utiliza.

En cualquier caso, y como tú mismo comentas, la recomendación más extendida consiste en enlazarlo o incluirlo al final de la página, justo antes de la etiqueta </body> de cierre.

Las buenas prácticas de Yahoo! sobre rendimiento de aplicaciones indican lo siguiente al respecto:

El problema de los scripts es que mientras se descargan, bloquean la descarga de otros contenidos importantes de la página, como por ejemplo las imágenes.

No obstante, las mismas buenas prácticas de Yahoo! indican que a veces es imposible enlazar el código JavaScript al final de la página, como por ejemplo cuando el código modifica el contenido de la página con instrucciones de tipo document.write(...).

Técnicas para mejorar la carga de los archivos JavaScript externos

Aunque el código JavaScript esté enlazado en el elemento <head>, puedes impedir que penalice el rendimiento si utilizas una técnica como la de Google Analytics, que crea el enlace al código JavaScript dinámicamente y lo carga asíncronamente (mediante el atributo async):

<!DOCTYPE html>
<html>
<head>
...
<script type="text/javascript">
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXX-X']);
  _gaq.push(['_trackPageview']);
 
  (function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript';
    ga.async = true;
 
    ga.src =
      ('https:' == document.location.protocol ? 'https://ssl' : 'http://www')
      + '.google-analytics.com/ga.js'
    ;
 
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(ga, s);
  })();
 
</script>
</head>
<body>
...
</body>
</html>

Otra técnica consiste en utilizar el atributo defer, que indica al navegador que el código JavaScript enlazado se puede descargar y procesar después de que la página se haya cargado completamente:

<!DOCTYPE html>
<html>
<head>
  ...
  <script type="text/javascript" defer src="..."></script>
</head>
<body>
...
</body>
</html>

El problema del atributo defer es que su comportamiento no es idéntico en todos los navegadores y obliga a ejecutar los scripts en el mismo orden en el que se definen en la página, por lo que en este caso también se pueden producir bloqueos (algo que no sucede por ejemplo con el atributo async de la técnica anterior).

Por último, las buenas prácticas de Google para el rendimiento de aplicaciones aconsejan utilizar la siguiente técnica:

Identifica todos los archivos JavaScript de tu sitio o aplicación en los que haya más de 25 funciones que no se utilicen antes del evento onload de la página. No cargues ninguno de esos archivos en el <head> y utiliza en su lugar la carga asíncrona de archivos.

Para aplicar esta técnica, Google recomienda utilizar el siguiente código para cargar esos archivos con más de 25 funciones sin utilizar:

<script type="text/javascript">
function cargarCodigoJavaScript() {
    var element = document.createElement("script");
    // el archivo `codigo_javascript.js` contiene todo el código
    // JavaScript que no se ejecuta antes de cargar la página
    element.src = "codigo_javascript.js";
    document.body.appendChild(element);
}
 
if (window.addEventListener) {
    window.addEventListener("load", cargarCodigoJavaScript, false);
} else if (window.attachEvent) {
    window.attachEvent("onload", cargarCodigoJavaScript);
} else {
    window.onload = cargarCodigoJavaScript;
}
</script>
#2

Es un tema que puede generar bastante controversia. Una buena práctica es integrarlo antes del cierre de la etiqueta </body> , pero que aveces sería algo imposible cuando necesitamos modificar el DOM cuando se está cargando la página.

En esos casos siempre es recomendable dejarlo dentro de la etiqueta <head> es 100% práctico siempre y cuando le adviertas al script que se cargue después de que el DOM esté totalmente cargado, lo puedes hacer con el evento load del objeto window en el código JavaScript:

// código Js
window.onload = function() {
   /* Aquí la instancia a eventos desde elementos que ya
      están cargados dentro de la página */
}