Modelo mental de JavaScript: lenguaje, runtime y diseño | Nicolás Garzón
JavaScript se entiende mejor como un conjunto de capas conectadas, no como una lista de sintaxis aislada.
Texto
Copiar valores y bindings
↓
expresiones y control
↓
scopes y contextos
↓
funciones y closures
↓
objetos y prototipos
↓
colecciones e iteración
↓
errores y contratos
↓
Event Loop y promesas
↓
módulos y dependencias
↓
APIs del host
↓
memoria, rendimiento y seguridad
JavaScript
Copiar const product = {
id : "p1" ,
price : 100 ,
} ;
const crea un binding.
El binding guarda un valor de referencia.
El objeto tiene identidad y es mutable.
const impide reasignar el binding, no modificar el objeto.
JavaScript
Copiar let value = 10 ;
value = "ten" ; Los valores tienen tipos; una variable no queda ligada para siempre a uno.
La flexibilidad exige contratos claros y validación en fronteras.
JavaScript
Copiar const total = price * quantity; Las sentencias controlan ejecución:
JavaScript
Copiar if ( total > limit) {
throw new RangeError ( "Limit exceeded" ) ;
} JavaScript
Copiar const tax = 0.19 ;
function calculate ( price ) {
return price + price * tax;
} La función resuelve tax según el lugar donde fue definida, no desde donde se llama.
Texto
Copiar scope actual
↓
scope exterior
↓
global o móduloJavaScript
Copiar calculate ( 100 ) ; Se crea un contexto con parámetros, variables y referencias léxicas. El Call Stack organiza llamadas activas.
Al retornar, el frame sale del stack; los datos capturados por closures pueden continuar alcanzables.
JavaScript
Copiar function createValidator ( limit ) {
return ( value ) => value <= limit;
}
Guardarse.
Pasarse.
Retornarse.
Capturar bindings.
Ejecutarse de forma síncrona o como callbacks posteriores.
Una callback no es asíncrona por definición; depende de quien la invoque.
JavaScript
Copiar const user = Object. create ( baseUser) ; Si una propiedad no existe en user, JavaScript recorre su cadena de prototipos.
Las clases organizan este modelo; no lo reemplazan.
JavaScript
Copiar class User {
greet ( ) { }
} greet vive normalmente en User.prototype.
JavaScript
Copiar object. method ( ) ; El receptor determina this en una función normal.
JavaScript
Copiar const method = object. method;
method ( ) ; Extraerla pierde ese receptor. Las arrow functions capturan this léxicamente.
Texto
Copiar Array → orden y posición
Map → clave-valor dinámica
Set → valores únicos
WeakMap → metadatos ligados a una clave vivaElegir la estructura adecuada simplifica algoritmos y comunica intención.
JavaScript
Copiar for ( const value of iterable) { } Un iterable sabe crear un recorrido. Un iterador entrega valores. Un generator facilita producir secuencias pausables.
La iteración asíncrona añade espera entre pasos.
JavaScript
Copiar function requireProduct ( id ) {
const product = findProduct ( id) ;
if ( ! product) {
throw new ProductNotFoundError ( id) ;
}
return product;
} No todo resultado negativo es una excepción. El contrato decide si la ausencia es normal o impide continuar.
Capturar no significa resolver; una capa maneja solo aquello que comprende.
Texto
Copiar motor
+ Call Stack
+ Event Loop
+ APIs del hostEl lenguaje no incluye DOM, fetch o localStorage.
El host ejecuta operaciones externas y encola continuaciones.
Una callback actual termina antes de que otra task empiece en el mismo agente.
JavaScript
Copiar console. log ( "A" ) ;
setTimeout ( ( ) => console. log ( "B" ) , 0 ) ;
console. log ( "C" ) ; JavaScript
Copiar Promise. resolve ( ) . then ( ( ) => {
console. log ( "microtask" ) ;
} ) ; Promesas y continuaciones de await utilizan jobs procesados como microtasks en el host.
Una cadena infinita de microtasks también puede bloquear renderizado.
JavaScript
Copiar const promise = loadProduct ( ) ; Puede terminar fulfilled o rejected. Cada then crea otra Promise y adopta el retorno de la callback.
JavaScript
Copiar loadUser ( )
. then ( ( user ) => loadOrders ( user. id) )
. catch ( handleError) ; Olvidar return rompe la cadena.
JavaScript
Copiar const data = await loadData ( ) ; No bloquea todo el runtime ni crea otro hilo. La función devuelve control y continúa después.
Durante la espera, el estado externo puede cambiar. Por eso existen cancelación, IDs de versión y control de race conditions.
JavaScript
Copiar await Promise. all ( items. map ( processItem) ) ; Inicia todo. Puede saturar recursos.
Un pool controla cuántas operaciones están activas. Reintentos necesitan clasificación e idempotencia.
JavaScript
Copiar import { createOrder } from "./orders.js" ; Imports son live bindings de solo lectura local. Las dependencias se enlazan antes de evaluar y los ciclos pueden observar bindings no inicializados.
Los módulos deben exponer APIs pequeñas y efectos explícitos.
JavaScript
Copiar document;
fetch;
localStorage;
indexedDB;
Worker;
Contexto.
Permisos.
Tiempo de vida.
Errores.
Cleanup.
Compatibilidad.
Datos de estas APIs continúan siendo no confiables.
Un valor vive mientras exista una ruta desde las raíces.
JavaScript
Copiar const cache = new Map ( ) ; Una cache, listener o closure puede conservar datos. Garbage collection no cierra recursos externos; utiliza cleanup explícito.
Texto
Copiar métrica → perfil → hipótesis → cambio → mediciónAlgoritmos, red, DOM, bundle, memoria y capacidad de respuesta forman parte del costo.
El motor observa rutas y tipos, compila código caliente y deoptimiza cuando cambian supuestos.
Hidden classes y JIT son detalles de implementación. El contrato portable sigue siendo ECMAScript.
JavaScript
Copiar element. textContent = userInput; Un string válido puede ser peligroso si se interpreta como HTML, URL, SQL o código.
Valida datos.
Codifica para el destino.
Autoriza en el servidor.
No expongas secretos en frontend.
Limita dependencias y recursos.
JavaScript
Copiar expect ( calculateTotal ( items) ) . toBe ( 30 ) ; Prueba resultados, errores, límites, efectos y asincronía. Coverage no reemplaza assertions útiles.
¿Qué diferencia hay entre binding y valor?
¿Por qué dos objetos iguales visualmente no son ===?
¿Cómo resuelve JavaScript un nombre?
¿Qué mantiene vivo un closure?
¿Cómo se determina this?
¿Qué hace realmente new?
¿Cómo funciona la cadena de prototipos?
¿Qué diferencia hay entre task y microtask?
¿Por qué fetch 404 no rechaza normalmente?
¿Qué retorna una función async?
¿Por qué forEach no espera callbacks async?
¿Qué es un live binding?
¿Qué diferencia hay entre lenguaje y Web API?
¿Cuándo puede recolectarse un objeto?
¿Cómo encontrarías una fuga de memoria?
¿Qué métrica optimizas?
¿Dónde debe validarse una respuesta externa?
¿Qué comportamiento protege una prueba?
Notas de nivel Esencial en orden.
Notas Aplicado , escribiendo ejemplos propios.
Notas Avanzado , conectándolas con debugging y casos reales.
Predice resultados antes de ejecutar.
Explica el Call Stack en voz alta.
Dibuja scope y referencias.
Reescribe callbacks como promesas.
Encuentra el orden de tasks y microtasks.
Diseña una API de módulo pequeña.
Perfila un flujo real.
Corrige un bug y añade su prueba.
No necesitas recordar cada método de cada API.
Qué problema resuelve.
Qué recibe.
Qué devuelve.
Cómo falla.
Si muta.
Si espera.
Qué referencias conserva.
Qué entorno la proporciona.
Cómo se limpia.
JavaScript conecta valores, scope, funciones, objetos y ejecución.
Los prototipos explican delegación y clases.
Promesas modelan continuaciones futuras.
El Event Loop pertenece al runtime.
Módulos forman un grafo y exponen contratos.
Web APIs no son el lenguaje.
La memoria depende de reachability.
Rendimiento y seguridad necesitan contexto y medición.
Testing protege comportamiento.
Una base sólida permite aprender frameworks sin depender de magia.
Cuando una característica parezca extraña, vuelve a estas preguntas:
Texto
Copiar ¿Qué valor existe?
¿Qué binding lo referencia?
¿En qué scope se busca?
¿Qué llamada se está ejecutando?
¿Qué objeto recibe this?
¿Qué operación se encoló?
¿Qué Promise representa el resultado?
¿Qué módulo o host ofrece la API?
¿Qué referencia mantiene vivo el dato?
¿Qué contrato debería comprobarse?Responderlas convierte muchos comportamientos de JavaScript en consecuencias previsibles, no en reglas aisladas para memorizar.