Hoisting de Javascript

Explicado de un modo muy breve, consiste en que javascript, en el momento de compilar el código, prioriza las declaraciones de variables, siendo lo primero a tratar dentro de cada contexto. Es importante tener en cuenta que esto no aplica para las asignaciones, únicamente para la declaración. Estudia el siguiente script:

/*
 * Logamos 'undefined' por que la declaración de x ha sido alzada
 * por encima de esta función, pero no su asignación. Observa,
 * no obstante, que no recibimos un error de referencia a x a pesar
 * de que la línea dónde se declara y asigna está justo debajo.
 */
console.log("x:", x)
var x = "Primera asignación";

//Ahora sí logamos 'Primera asignación'
console.log("x:", x)

(function () {
 /* No logamos 'Primera asignación' sino 'undefined', porque la
  * segunda declaración ha sido elevada al inicio de su contexto,
  * sobrescribiendo a la primera declaración y asignación.
  */
  console.log("x:", x);
  var x = "Segunda asignación";

  // Ahora sí, logamos 'Segunda asignación'
  console.log("x:", x);
}());