Si abres la consola del navegador, con la combinación de teclas Ctrl + Shift + I o clic derecho e "Inspeccionar" en tu navegador preferido (de preferencia Google Chrome).
Ejecuta la palabra window, se desplegará un objeto en el que se encuentran todas las funcionalidades de JavaScript, por ejemplo ejecuta window.console.log("Hola") tendrá el mismo comportamiento que console.log("Hola").
Si ejecutas this observarás que muestra el mismo objeto que window, esto es porque en un contexto global, estos dos objetos son iguales. Pero en otros contextos, como el de una función o una clase, this cambia.
Qué es hoisting
Hoisting es un término para describir que las declaraciones de variables y funciones son movidas a la parte superior del scope más cercano: scope global o de función. Esto sucede solamente con las declaraciones y no con las asignaciones.
El código permanece igual, solo es una interpretación del motor de JavaScript que intenta ayudar a optimizar el código, pero en este caso provoca errores y resultados no esperados. En el caso de las variables solo sucede cuando son declaradas con var.
Hoisting en variables declaradas con var
En el siguiente código, la respuesta del console.log es undefined, porque al hacer referencia a una variable que no está declarada, el motor de JavaScript crea esta variable antes de la declaración y le asigna un valor de undefined.
console.log(nombre)// undefinedvar nombre ="Andres"
var nombre =undefinedconsole.log(nombre)nombre ="Andres"
Lo adecuado es evitar utilizar var para declarar las variables con let o const, ya que estas últimas el proceso de optimización que realiza el motor de JavaScript no generará variables con el valor de undefined antes de su declaración.
Una preguntica de examen
Una estricta definición de hoisting sugiere que las declaraciones de variables y funciones son físicamente movidas al comienzo del código,asignandolas en memoria dentro de un contexto de ejecucion.
Si llamamos una variable antes de ser declarada, el compiler crea la variable en la memory heap y la inicializa como undefined
En el caso de las funciones es distinto, primero mandamos a llamar a las funciones antes de ejecutarlas.
El hoisting a veces funciona pero no tenemos control de las variables que se van a cambiar
Si llamamos a una constante (const) antes de inicializar retorna un error de tipo: Uncaught ReferenceError, que corresponde a variables que son referenciadas pero no pudieron ser capturadas
Estimado Alex, por lo que hizo el prof en clase, que con ellos aunque te equivoques en llamar a una variable antes de ser declarada, el hoisting ya no se aplique en ellas y así se evita problemas en el proceso de lo que quieres hacer con tu código de JavaScript
Zona muerta temporal
Es el lugar donde se guardan las variables declaradas con let y const, cuya función es impedir el acceso a ellas antes de ser inicializadas. Por eso es mejor usar let y const por sobre var
Parser => Significa analizar y convertir un programa a un formato interno que un entorno de ejecución pueda ejecutar, por ejemplo, el motor JavaScript dentro de los navegadores.
Pero, si declaras una variable y le asignas un valor en la misma linea el resultado es diferente:
var nombre ="Platzi";functionnombre(){}typeof nombre;// Output: "string"
Esto es porque JavaScript hace hoisting solo de la declaración de la variable. JavaScript trata la declaración y asignación en una sola linea como dos pasos, por lo que si escribimos:
var nombre ="Platzi";
El motor lo interpreta así:
var nombre =undefined;nombre ="Plazi";
Así que cuando escribimos:
var nombre ="Platzi";functionnombre(){}typeof nombre;// Output: "string"
Como lo interpreta el motor de JavaScript es así:
var nombre =undefined;functionnombre(){}nombre ="Platzi";typeof nombre;// Output: "string"
Es decir que "se deja atrás" la asignación.
Obviamente ningún desarrollador debería de escribir código así de confuso, esto es solo para saber como funciona JavaScript y su engine, ese conocimiento te hace un mejor desarrollador y te destaca de entre otros.
Cuando el motor JS obtiene nuestro script, lo primero que hace es configurar la memoria para los datos de nuestro código. No se ejecuta ningún código en este punto, simplemente está preparando todo para su ejecución. La forma en que se almacenan las declaraciones de función y las variables es diferente.
.
Las funciones se almacenan con una referencia a la función completa:
.
Con las variables es un poco diferente. ES6 introdujo dos nuevas palabras clave para declarar variables: let y const. Las variables declaradas con la palabra clave let o const se almacenan sin inicializar:
.
Las variables declaradas con la palabra clave var se almacenan con el valor predeterminado de undefined:
.
Ahora que ha terminado la fase de creación, podemos ejecutar el código. Veamos qué sucede si tuviéramos 3 sentencias console.log encima del archivo, antes de declarar la función o cualquiera de las variables.
Dado que las funciones se almacenan con una referencia a todo el código de la función, podemos invocarlas incluso antes de la línea en la que las creamos:
.
Cuando hacemos referencia a una variable declarada con la palabra clave var antes de su declaración, simplemente devolverá su valor predeterminado con el que se almacenó "undefined". Sin embargo, esto a veces puede provocar un comportamiento "inesperado". En la mayoría de los casos, esto significa que le estás haciendo referencia sin querer (probablemente no quieras que tenga el valor de undefined):
.
Para evitar poder hacer referencia accidentalmente a una variable undefined, como podríamos hacer con la palabra clave var, se lanzará un ReferenceError cada vez que intentamos acceder a variables no inicializadas.
La "zona" antes de su declaración real se denomina "zona muerta temporal". No puede hacer referencia a las variables (¡esto también incluye las clases ES6!) antes de su inicialización:
.
Cuando el motor pasa la línea en la que realmente declaramos las variables, los valores en la memoria se sobrescriben con los valores con los que realmente los declaramos (hay un pequeño error en la animación, debiera ser la número 7 y no la 6):
.
++Resumen rápido:++
– Las funciones y variables se almacenan en la memoria para un contexto de ejecución antes de ejecutar nuestro código. A esto se le llama Hoisting .
– Las funciones se almacenan con una referencia a la función completa, las variables con la palabra clave var con el valor de undefined y las variables con la palabra clave let y const se almacenan sin inicializar.
El hoisting es un poseso de compilador de JS que consiste en que la declaración de las variables y las funciones son llevadas a l inicio del código sin importas sus propiedades, para su procesamiento sin embargo, la inicialización de las variables no es llevada al inicio del código para su compilación, si no solo su declaración, lo suele dar espacios a errores cuando se declara una variable sin inicializarla y se procesa en el código antes de haber llegado a sus inicialización lo cual nos suele dar una variable con calor undefined, ya que la variables si fue almacenada en la memoria, pero no se asigno un valor asta después de la ejecución ejemplo :
saludo()functionsaludo(){console.log("Hola"+ nombre)}var nombre ="Miguel"
El resultado sera
Holaundefined
En base a este ejemplo fue porque se cometió el error de usar la variable antes de inicializar pues sin problema el compilador le asigna memoria pero no el valor asta después.
Le asigna memoria a la variable y le da valor de undefined a suceder la asignación de memoria.
var nombre =undefined;functionsaludo(){console.log("Hola"+ nombre);}saludo()
Aqui como hemos visto que la variable como undefined y posterior mente se utiliza al llegar a l alinea del saludo()
Pero si declaro si hago este siguiente codigo me va a regresar el nombre que le puse a la variable, le puse comillas para separar el hola y el nombre
var nombre =undefined;functionsaludo(){console.log("Hola"+" "+ nombre);}var nombre ="Miguel";saludo()
el resultado seria Hola Miguel
La forma de hacer que corrercta de hacerlo es esta
var nombre ="Miguel";functionsaludo(){console.log("Hola"+" "+ nombre)}saludo()