Les comparto un artículo que escribí acerca del tema.
.
Introducción al curso
Requisitos antes de empezar
Historia de JavaScript
JavaScript Engine
¿Cómo funciona el JavaScript Engine?
V8, el JavaScript Engine de Chrome
Profundizando en el Engine
Ejemplo de Objeto global y hoisting
Código de Ejecución
Memory Heap
Qué es Call Stack
Garbage Collection
Qué es Stack overflow
JavaScript Runtime
Qué es la asincronía en JavaScript
Recapitulación
Create an account or log in
Keep learning for free! Join and start boosting your career
Once a file is executed in the browser, the JavaScript engine generates a global environment. The global environment does three very important things:
window
.this
. In a global context this
is equal to window
.After generating the global environment, it starts the Execution context where it runs the JavaScript code using a Stack of tasks, stacking them one by one, in which the last task added will be the first to be executed.
Once the JavaScript engine is interacting with the browser, it performs the following processes:
Parser: generates a parse of the entire document using keywords.
AST: It is created from the nodes generated by the parser. It is a tree structure that represents your code syntactically. You can use the AST Explorer{target="_blank"} page to see how it works.
Interpreter: The interpreter goes through the AST and generates Bytecode (language that the computer understands and is not binary) based on the information it contains. However, if the interpreter detects that it can optimize your code, it does not generate Bytecode, but generates an optimization process consisting of the profiler and compiler.
Profiler and compiler: The profiler monitors and looks at the code to optimize it. The compiler optimizes that code and generates machine code (binary language). At this stage, due to the intention of optimizing the code, it also generates errors such as Hoisting.
Contribution created by Andres Guano.
Contributions 85
Questions 13
Les comparto un artículo que escribí acerca del tema.
.
Les comparto este fragmento de un apunte por si alguien quería saber la diferencia entre bytecode y Machine code como yo
Esto, el hoisting, event loop y otros conceptos en este curso son cosas muy preguntadas en las entrevistas para JS developer (Front o Back) entonces aquí si vale mucho crear notas 😉 (Y)
Engine es un intérprete que compila código JavaScript a bytecode.
.
El navegador genera un entorno global -> window
hace 3 cosas
Aqui pas al contexto de ejecucion (execution context)
y Lugo si corre el codigo: Lo corre a travez de un stack de tareas, las aplia una a una
JS -> parser -> AST abstrac sintax tree -> interpreter -> Bytecode (no es lengauje de maquina) pero lo entiende la maquina
Si el interpreter, se da cuenta que hay codigo que puede optimizar,
interpreter -> Profiler (monitor) -> compiler -> otimized code [aqui es donde ocurre el hoisting].
aqui es donde eventualmente se generan errores, ya que la maquina trata de optimizar o mejorar el codigo
y es donde se pueden dar errores desonocidos.
Es necesario tratar de evitar el hoisting
el hoisting ocurre con variables y funciones que se mandan llamar
Dos preguntas de examen:
Cuando hablamos de Windows, nos referimos a un objeto global, tambien se crea una variable llamada This, que hace referencia al objeto global de windows.
Pasos de ejecución de un código JS
Si en el parseo del árbol, el interprete se da cuenta que hay código duplicado
En este proceso se general el Hoisting
RESUMEN: Al momento de interpretar el código suceden diferentes cosas por detrás, lo mas importante es que se convierte a código maquina y se optimiza si hay código duplicado generando algo llamado hoisting
Justamente esto del entorno global es uno de los bugs mas comunes en JavaScript ya que aveces llamas una función o variable en un bloque de código y te aparece undefined ya que el this de esta función está apuntando al window o entorno global y tu quieres que apunte al entorno local…tiene que ver con los scopes de las variables.
Si quieren saber cómo se ve el bytecode pueden crear un archivo (en este ejemplo index.js
) y usar el siguiente comando:
node --print-bytecode index.js
Hoisting: es el comportamiento predeterminado de JavaScript de mover las declaraciones a la parte superior.
1.- Una vez que corre el archivo en el engine, antes de empezar a traducir, GENERA UN ENTORNO GLOBAL,
2.- Se genera el objeto principal que se llama WINDOW
3.- Despues genera una variable que se llama "this"
4.- Empieza a correr nuestro código en el contexto de ejecución, lo corre a traves de un stack de tareas (las apila una por una)
5.- Ya que esta interactuando el motor con el navegador, genera un PARSEO del documento completo,
lo cual le ayuda a encontrar las claves principales (key words)
6.- Se genera el Arbol de sintaxis abstracta (AST) con las key words, el cual va a parsear el navegador despues
7.- Interpreta el arbol (y ahi entra un profiler que ayuda a optimizar el código) JUSTAMENTE donde entra el HOISTING
8.- Al final genera Bytecode el cual entiende la maquina
window
.this
que depende del contexto en el que se llame, en el entorno global ó global scope, this
es igual a window
.Es la forma cómo se corre el código que es en forma de pila.
El archivo de JS primero se parsea mediante AST (Sintaxis de Árbol Abstracta) para identificar las variables y las funciones y entender que parametros cumplen en esa sintaxis. Finalmente se genera Bytecode que es una forma en que entiende el navegador. También el motor puede optimizar algunos pasos en caso que vea que haya código repetido.
Hoisting es el comportamiento por defecto de JavaScript en el que la declaración de variables y funciones se mueve automáticamente al principio del scope (ya sea el principio del archivo, la función o el bloque). Mira este ejemplo:
greetMiguel()
function greetMiguel() {
console.log("Hello Miguel")
}
A pesar de que estamos invocando la función **greetMiguel **antes de definirla, esto funciona; la declaración de la función se mueve al principio del archivo antes de ejecutarlo.
La declaración de las variables también se mueve, pero no la inicialización. Mira este ejemplo:
console.log(name);
let name = 'Miguel Soler';
El resultado de este código es undefined porque, aunque la declaración de name se mueve al principio, la inicialización no. El anterior código es igual a:
let name;
console.log(name);
name = 'Miguel Soler';
Por esta razón, si asignamos una función a una variable, la función no se mueve al principio y no la vamos a poder invocar antes:
greetMiguel(); // Error, greetMiguel is not a function
const greetMiguel = function() {
console.log("Hello Miguel");
}
Lo mismo ocurriría si cambiamos la función por una función flecha.
Recuerda y repítelo a diario: Lo que se mueve es la declaración de la variable, no la inicialización.
Global Environment: Entorno Global
Global Object: Objeto Global
This: Variable que depende del contexto
Outer environment: Entorno Externo
Execution Context: Contexto de Ejecución para las tareas
El AST es genial porque gracias a el podemos desarrollar nuestras propias reglas para ESLint, en el curso profesional de JavaScript te enseñan esto, y básicamente el bytecode es muy parecido a código de los niveles de Assembler jaja
En el curso de JavaScript Profecional con @sparragus se explica un poco mejor y con mas detalles.
En el curso de Fundamentos de javascript vemos algo sobre este tema y el cuidado que hay que tener con this.
Global Enviroment
Global Object - this - Outer Envoroment
El entorno Global
1 - Genera un objeto global que se llama window
2 - genera variable this quien en el entorno global hace referencia a window
3- Outer envoroment - Entorno exterior
Después se crea el Contexto de ejecución
Donde se empieza a correr nuestro código a través de un stack de tareas en donde se apilan una a una.
index.js
Parser
Analiza el codigo JS enviado para organizarlo, encontrando keywords y dando sentido para empezar al siguiente paso
AST (Abstract syntax tree)
Se cosntruye una sintaxis en forma de arbol que crea un orden idoneao para despues compilar a lenguaje maquina.
Profiler (monitor)
En este proceso se identifica si el codigo puede ser optimizado antes de pasarlo a Byte code relizando optimizacion y facilitando asi la interpretacion.
Interpreter
Aquí se interpreta el árbol y convierte el codigo JS en ByteCode
Bytecode
En la etapa de interpreter, profiler y compiler se crea el hoisting, si no se le da un adecuado manejo nos puede generar algunos inconveniente ya que al tratar de optimizar nuestro código el motor nos puede provocar algunos errores indeseados.
-Pasear sígnifica analizar y descomponer un STRING (conjunto de caracteres) escrito en un LENGUAJE FORMAL
-DESCOMPONER significa DIVIDIR el STRING según reglas y key-words del lenguaje
-ANALIZAR significa darle un sentido a esas descomposiciones , gracias a las key-words y reglas
-EL objetivo de parsear es producir una estructura de ejecución (ARBOL-TREE) y que sea capaz de entenderlo una computadora
No entiendo, según el profesor la maquina entiende y ejecuta Bytecode y ya, pero he estado investigando y decían que pasa a Machine Code y ahí se ejecuta.
Aquí no explican a profundidad; el hecho de que el motor funciona con un interprete y compilador y que el código optimizado es Machine Code y demas.
this
.Hoisting
Hoisting, no hosting
Entendiendo como funciona V8
¿Cómo lo hicieron?
Entre todas las razones, la principal está en los conceptos compilador e intérprete.
El compilador es el programa encargado de convertir código escrito en un lenguaje de programación a otro lenguaje de programación de bajo nivel. Por ejemplo, el compilador del V8 es el encargado de transformar JavaScript a Bytecode y luego a Machine Code.
Por otra parte, el intérprete es el encargado de revisar el código línea por línea y ejecutarlo directamente en la máquina de destino. Cabe resaltar que los intérpretes también realizan algún trabajo de traducción al igual que los compiladores.
Cuando llega un script al navegador el motor V8 inicia un proceso el cual consta de:
Recibir el código JavaScript como un flujo de bytes UTF-16 y pasarlo a un decodificador de flujo de bytes (el cual hace parte del motor).
Parsear (transformar) el código y descomponerlo en tokens (los tokens son elementos de js como: let, new, símbolos de operaciones, functions, promises).
Gracias a el anterior parseo se genera una estructura de datos en forma de árbol, o bien, Abstract Syntax Tree (AST). V8 cuenta con dos tipos de parseo que verás más abajo.
El intérprete recorre el AST y va generando el bytecode.
Luego de interpretar todo el código, el profiling data va evaluando el bytecode varias veces más y de esta forma descubre que puede enviarle al optimizing compiler, el cual se encarga de optimizar el código bytecode a machine code y así se reemplaza el código base para ejecutar el código JavaScript más rápido y usar menos recursos.
El optimizing compiler encuentra los puntos donde el código se puede optimizar. Normalmente optimiza el código que se repite varias veces. En caso de que la operación cambie por alguna razón, el código vuelve a la versión anterior (la des-optimizada). Esto se hace para consumir menos recursos y por lo tanto ejecutar el código más rápido.
más info: https://dev.to/johncardenasp/como-funciona-el-motor-de-javascript-jfb
Una vez que el motor corre el archivo de JavaScript, lo primero que hace es generar un entorno global, y procede a realizar 3 pasos.
Luego, cuando JavaScript empiece a interactuar con el navegador ocurre un parseo (digamos que es una inspeccion) del documento completo para encontrar las keywords y mandarlas al Abstract Syntax Tree (AST), que es una estructura de árbol donde podemos ver como estan estructuradas las keywords (variables, funciones, objetos, todo en si) por dentro. https://astexplorer.net/
Ahora que tiene el árbol sintáctico listo con las keywords desestructuradas, comienza a interpretar el código y lo convierte en bytecode (que no es tan bajo como machine code, pero la máquina si puede entenderlo).
Antes de convertirlo en bytecode, puede ocurrir un paso interior donde si el motor detecta que el código puede ser optimizado (debido a que hayan variables repetidas, funciones declaradas, y errores en el código) por el motor en un intento de ayudarnos a que no ocurran errores, y una vez que lo optimiza, lo compila y lo convierte en bytecode. En este proceso puede ocurrer el Hoisting (levantamiento) donde una variable (sucede mas que todo con var y function) es subida y guardada en memoria antes de ejecutar cualquier tipo de código, y puede devolvernos un comportamiento erróneo de nuestro código.
Como V8 trata nuestro código, abrir imagen en nueva pestaña para mejor calidad
AST = abstrac sintax tree
El Bytecode es un código intermedio que se puede tomar como un binario ejecutable. Su utilidad es que corre independientemente de la arquitectura de la computadora y de el sistema operativo.
El Bytecode aún necesita un interprete para ser ejecutado, ya que se necesita convertir ese Bytecode al set de instrucciones adecuado para la arquitectura en la que se corre.
En el Curso Básico de JavaScript explica que es el Hoisting, podemos repasar la clase Aqui!
hoisting, es cuando usas variables sin haberlas declarado antes
ejemplo
var duplicarEdad = edad * 2
var edad = 31;
Esto es lo visto en un capitulo del curso profesional de js pero mas desglosado
El tener buenas prácticas no solo ayuda a que el código sea mas legible, también ayuda a convertir nuestro código a lenguaje maquina
Les comparto el siguiente artículo para entender un poco mejor this
:
.
This en diferentes situaciones y su comportamiento:
https://filisantillan.com/this-en-diferentes-situaciones-y-su-comportamiento/
Global Environment: Entorno Global
Global Object: Objeto Global
This: Variable que depende del contexto
Outer environment: Entorno Externo
Execution Context: Contexto de Ejecución para las tareas
Profile nos ayudar optimizar nuestro codigo para cuando se genera el Bytecode
AST -> Arbol de sintaxy
Genial explicado, creemos que es magia lo que ocurre ya que lo hace muy rápido pero luego explicado todo cobra sentido aunque sigue con algo de magia 😄
Esto lo escuché por primera vez en el curso profesional de Javascript, y esta explicación me complementó aquella información. Increíble lo que pasa internamente
Profile nos ayudar optimizar nuestro codigo para cuando se genera el Bytecode
Listo…
En terminos sencillos y hasta donde he entendido, los pasos sería:
Análisis léxical: Primero cuando la web y la maquina detecta un archivo javascritp y donde se decompone el código en partes pequeñas llamas tokens y se analiza (parse) las palabras claves, funciones, etc
Abstract Syntax Tree (AST): Aqui es donde a partir de los tokens, se realiza un áboles donde va a representar la estructura y lógica
Compilación y optimización: Aqui esta el Just In Time (JIT) y compila el códgio
Ejecución: El código de maquina resultante ejecuta el código según las instrucciones del AST
Este video muestra de manera visual qué pasa detrás de cada proceso 👉 Understanding the V8 JavaScript Engine
En el contexto de V8, Bytecode y Machine code son dos tipos diferentes de códigos que se generan en diferentes etapas del proceso de compilación y ejecución del código JavaScript.
.
Bytecode es un código intermedio que se genera a partir del código fuente JavaScript durante la fase de compilación. El bytecode se compila en tiempo de ejecución y se ejecuta en la máquina virtual de V8. El bytecode se utiliza para acelerar la ejecución del código JavaScript, reduciendo el tiempo necesario para compilar y optimizar el código en tiempo de ejecución. El bytecode de V8 se llama “Bytecode Ignition”.
.
Por otro lado, el Machine code es el código de bajo nivel que se ejecuta directamente en la CPU. Durante la fase de optimización, V8 compila el bytecode en un código de máquina altamente optimizado que se ejecuta directamente en la CPU. El código de máquina se llama “TurboFan”. El código de máquina es mucho más rápido que el bytecode, ya que se ejecuta directamente en la CPU sin la sobrecarga de la máquina virtual.
.
En resumen, Bytecode es un código intermedio generado durante la fase de compilación y se ejecuta en la máquina virtual de V8, mientras que el Machine code es el código de máquina altamente optimizado generado durante la fase de optimización y se ejecuta directamente en la CPU. El bytecode se utiliza para acelerar la compilación y la optimización del código en tiempo de ejecución, mientras que el código de máquina se utiliza para obtener el máximo rendimiento durante la ejecución del código JavaScript.
Hice mi resumen…espero se entienda
Investigando un poco, encontre esto relacionado a la diferencia de bytecode y machine code:
el bytecode y el machine code son códigos de bajo nivel que se utilizan para ejecutar programas, pero el bytecode es un código intermedio generado por un compilador que es independiente de la plataforma, mientras que el machine code es el código de bajo nivel específico de la plataforma que se ejecuta directamente por el procesador.
Comparto este video creo que clarifica un poco el proceso
https://www.youtube.com/watch?v=JeyR30L_zmk
¿Sabes qué es Parser?
Significa analizar y convertir un programa en un formato interno que un entorno de tiempo de ejecución pueda ejecutar, por ejemplo, el motor de JavaScript dentro de los navegadores.
esta parte es valiosa, dice tal vez no tenga mucho sentido, pero es importante que puedas entende resto, que mano de carrrera tan barata y poca profundización en el tema, por fortuna los profesores como barajas salvan la carrera de javascript
v8
no entendi ni papa
que bonita quedó esa MAC.
El profiler (monitor) es el encargado de optimizar el código que mandamos. Aquí es donde ocurre el hoisting, un proceso que al no entenderlo puede causar errores en tu código.
Que tal compañeros, les dejo mis apuntes de la clase, de esta manera entiendo mejor los temas y se me es mas facil recordar depsues… espero les sirva
Profundizando en el Engine
Global Environment: Una vez se corre el archivo de JavaScript en el Engine, se crea una especie de entorno global. Al crearse el entorno global y hace tres cosas:
• Global Object
• Variable this
Después de crear mi objeto global y la variable de this (con el cual llamo mi objeto global), se genera algo llamado Execution Context (Contexto de ejecución): Es el momento en donde se empieza a correr nuestro código JS. Corriendo el código en un stack de tareas 1 por 1.
Al empezar a interactuar motor de JavaScript con el navegador es:
Buena info neni
y después escupe código binario…basten agresivo, me gusta zD
Excelente!
AST -> Arbol de sintaxy
Muy bueno
Al decir que Bytecode es el lenguaje interpretado por la maquina…
¿maquina se refiere al V8 Engine o al computador?
Genial
Les dejo este artículo muy explicativo: Contexto de ejecución
Interesante la comprensión de la estructura del motor😁😊
WHAT DOES THE ENGINE.
The engine once gets the code from the JavaScript file it does choose the main object “global object” that would be the window and its “this” references. After this process, it starts to create the “AST (Abstract syntax tree)” to be interpreted and translate it into Bytecode that the computer can understand.
Also, before translated the Engine will optimize the code but this help can bring some problems like the “hosting” between variables and function
Es cuando el motor de V8 al intentar ayudarnos a optimizar el codigo, nos puede generar algunos errores.
En este video Sacha lo explica de una manera muy didactica.
https://www.youtube.com/watch?v=uI6o97A4IrI
En este clase me quedaron mas claro algunos conceptos, que me estaban dando problemas. Genial
JS Engine es un mini programa que interpreta nuestro código y ejecuta un script de acuerdo a las instrucciones del código. Posteriormente, este es parseado es decir, va leyendo nuestro código línea por línea y revisa la sintaxis. Cuando detecta errores, detiene la ejecución, en caso de que todo vaya bien, entonces produce una estructura de datos llamada Abstract Syntax Tree (AST) después se traduce a código máquina y esta finalmente lo ejecuta.
Resumen:
Profundizando el Engine.
Cuando el motor de Js comienza a interactuar, empieza por realizar un Parseo(parser), esto le ayuda a encontrar las claves principales.Luego el resultado se pasa al AST(Abstract Sintax Tree). A continuacion se interpreta y se convierte a ByteCode.
Durante el interpretado si el interprete se da cuenta que hay mucho codigo para optimizar, actua el Profile(monitor), el cual ayuda a cumplir esta tarea. Al finalizar la optmizacion el codigo se compila y lo regresa como ByteCode.
Durante esta tarea es donde se puede encontrar el hoisting.
Una vez que corre nuestro archivo en el motor, lo que hace el navegador es crear un objeto principal llamado window que esta en un entorno global. Y este entorno global hace tres cosas, la primera es crear este objeto global llamado window, después genera una variable llamada “this” que hara referencia a nuestro objeto global. Ya que se crea este entorno global, se corre nuestro código y esto lo hace atreves de un stack de tareas que ira apilando una por una.
Si JS detecta que nuestro código se puede optimizar, toma el segundo camino, pero esto es por que seguimos malas practicas, y en este proceso de optimizado se genera algo llamado Hoisting. Esto funciona con variables y funciones y nos puede generar problemas.
si se usa "use strict" en el entorno global this no es asignado a window, es undefined.
Gracias muy bueno.
MY NOTES DEEPENING IN THE ENGINE 😄
En esta clase veremos que es lo que sucede mas a fondo en el motor de js
Una vez que corre el archivo de js en engine antes de empezar a traducirlo
genera un entorno global Global Environment
Este entono global es un objeto principal al cual se le llama window
El entorno global hace 3 cosas:
Despues de que genera estos dos el objeto global y variable this llega algo llamado Execution Context ya que genero este entorno global empieza a correr nuestro codigo
Esta parte de correr de codigo la hace atraves de un stack de tareas donde ira apilando cada una de ellas
Una vez el motor de js esta interactuando con el navegador
PARSING quiere decir analizar y convertir un programa en un formato interno que un ambiente que corre en tiempo real (Runtime) puede procesar, por ejemplo, el motor V8 de javascript en el navegador.
¿Qué es el hoisting?
https://platzi.com/clases/1807-scope/25867-que-es-el-hoisting/
Want to see more contributions, questions and answers from the community?