Top 50 Preguntas Frecuentes de JavaScript
Las 50 Preguntas Más Frecuentes de JavaScript
Section titled “Las 50 Preguntas Más Frecuentes de JavaScript”Guía completa con las preguntas que aparecen en la mayoría de entrevistas técnicas.
1. ¿Qué es JavaScript?
Section titled “1. ¿Qué es JavaScript?”Definición profesional: Lenguaje de programación interpretado, dinámico y débilmente tipado que se ejecuta en el navegador y en el servidor (Node.js). Motor V8 en Chrome/Node, SpiderMonkey en Firefox.
Características clave:
- Single-threaded con event loop para manejar asincronía
- Multiparadigma: funcional, orientado a objetos, basado en eventos
- Interpretado: no requiere compilación previa
Cómo responder en entrevista:
“JavaScript es un lenguaje dinámico single-threaded que usa el event loop para manejar operaciones asíncronas sin bloquear. Es multiparadigma: soporta programación funcional, orientada a objetos basada en prototipos y reactiva. Corre en el navegador y en el servidor con Node.js usando el motor V8.”
2. ¿Cuáles son los tipos de datos en JavaScript?
Section titled “2. ¿Cuáles son los tipos de datos en JavaScript?”¿Qué es? JavaScript tiene 7 tipos primitivos y tipos no primitivos (objetos).
Tipos primitivos:
- string: texto (
"Hola") - number: números enteros y decimales (
42,3.14) - boolean: verdadero/falso (
true,false) - undefined: variable declarada sin valor
- null: ausencia intencional de valor
- symbol: identificador único (ES6)
- bigint: números enteros grandes (ES2020)
Tipos no primitivos:
- object: colección de propiedades
- array: lista ordenada (es un objeto)
- function: bloque de código reutilizable (es un objeto)
Ejemplo práctico:
// Primitivoslet string = "Hola";let number = 42;let boolean = true;let undefined_var;let null_var = null;let symbol = Symbol('id');let bigint = 9007199254740991n;
// No primitivos (objetos)let object = { nombre: "Juan" };let array = [1, 2, 3];let function_var = function() {};Cómo responder en entrevista:
“JavaScript tiene 7 primitivos: string, number, boolean, null, undefined, symbol y bigint. Son inmutables y se comparan por valor. Todo lo demás es un objeto: arrays, funciones, fechas. Las funciones son objetos de primera clase.
typeof nullretorna ‘object’ por un bug histórico del lenguaje.”
3. ¿Qué es el DOM?
Section titled “3. ¿Qué es el DOM?”Definición profesional: Document Object Model: API que representa el HTML como un árbol de nodos accesible y manipulable desde JavaScript.
// Seleccionar elementoconst titulo = document.getElementById('titulo');const items = document.querySelectorAll('.item');
// Modificar contenidotitulo.textContent = 'Nuevo título';titulo.style.color = 'blue';
// Crear y agregar elementoconst parrafo = document.createElement('p');parrafo.textContent = 'Nuevo párrafo';document.body.appendChild(parrafo);Cómo responder en entrevista:
“El DOM es la representación en árbol del HTML que JavaScript puede leer y modificar. Uso
querySelectoryquerySelectorAllpara seleccionar (más flexibles quegetElementById). Las operaciones de DOM son costosas en rendimiento, por eso frameworks como React usan un Virtual DOM para minimizar los cambios reales.”
4. ¿Qué es el BOM?
Section titled “4. ¿Qué es el BOM?”Definición profesional:
Browser Object Model: API que expone objetos del navegador como window, navigator, location, history y screen.
// window - objeto globalwindow.location.href = 'https://ejemplo.com'; // Redirigirwindow.open('url', '_blank'); // Abrir pestaña
// navigator - info del navegador/dispositivoconsole.log(navigator.userAgent);console.log(navigator.language);
// history - historial de navegaciónhistory.back();history.pushState({}, '', '/nueva-ruta');Cómo responder en entrevista:
“El BOM es la API del navegador fuera del documento HTML.
windowes el objeto global: todas las variables globales son sus propiedades.locationmaneja URLs y redirecciones.history.pushState()es la base del routing de SPAs.navigator.geolocationynavigator.serviceWorkertambién son parte del BOM.”
5. ¿Cómo se declara una variable?
Section titled “5. ¿Cómo se declara una variable?”Definición profesional:
JavaScript tiene tres formas: var (función-scope, hoisting), let (bloque-scope, reasignable), const (bloque-scope, no reasignable). Usar const por defecto.
| var | let | const | |
|---|---|---|---|
| Scope | Función | Bloque | Bloque |
| Hoisting | Sí (undefined) | Sí (TDZ) | Sí (TDZ) |
| Reasignable | Sí | Sí | No |
// const - valor fijo (preferido)const PI = 3.14159;const usuario = { nombre: 'Juan' }; // El objeto puede mutarusuario.nombre = 'Pedro'; // OK - muta el objeto, no la referencia
// let - cuando necesitas reasignarlet contador = 0;contador = contador + 1; // OK
// var - evitar (scope de función, no de bloque)for (var i = 0; i < 3; i++) {}console.log(i); // 3 - escapa del for!Cómo responder en entrevista:
“Uso
constpor defecto para todo. Cambio aletsolo cuando necesito reasignar. Evitovarporque su scope de función causa comportamientos inesperados.constno significa que el valor sea inmutable: el objeto puede mutar, solo la referencia es fija.”
6. ¿Qué es el scope?
Section titled “6. ¿Qué es el scope?”Definición profesional:
Ámbito de visibilidad de una variable. JavaScript tiene scope global, de función, de bloque (let/const) y léxico (closures).
const global = 'Accesible en todo el código';
function ejemplo() {const funcionScope = 'Solo dentro de esta función';
if (true) { const bloqueScope = 'Solo dentro de este if'; var varEscapa = 'Escapa del bloque'; // Problema de var}
console.log(varEscapa); // Funciona (problema)// console.log(bloqueScope); // ReferenceError}Cómo responder en entrevista:
“Scope determina dónde vive una variable. El scope léxico significa que las funciones anidadas tienen acceso a las variables del scope padre.
vartiene scope de función (se eleva al inicio de la función),letyconsttienen scope de bloque. Las closures aprovechan el scope léxico para recordar el entorno de creación.”
7. ¿Qué es una función de primera clase?
Section titled “7. ¿Qué es una función de primera clase?”Definición profesional: En JavaScript las funciones son objetos de primera clase: pueden asignarse a variables, pasarse como argumentos, retornarse desde otras funciones y almacenarse en estructuras de datos.
// Asignar a variableconst saludar = function(nombre) { return 'Hola ' + nombre; };
// Pasar como argumento (callback)['Ana', 'Juan'].forEach(nombre => console.log(saludar(nombre)));
// Retornar función (Higher-Order Function)function multiplicador(factor) {return (numero) => numero * factor;}const duplicar = multiplicador(2);duplicar(5); // 10Cómo responder en entrevista:
“Las funciones son objetos de primera clase: pueden asignarse a variables, pasarse como callbacks y retornarse desde otras funciones. Esto habilita patrones funcionales como HOFs, currying y composición. Es la base de toda la programación funcional en JS y de APIs como
map,filteryreduce.”
8. ¿Qué es una función pura?
Section titled “8. ¿Qué es una función pura?”Definición profesional: Función que produce el mismo output para el mismo input y no tiene efectos secundarios (no modifica estado externo). Pilar de la programación funcional.
// PURA: mismo input = mismo output, sin efectos secundariosfunction sumar(a, b) { return a + b; }
// IMPURA - modifica estado externolet total = 0;function sumarImpura(valor) {total += valor; // Efecto secundarioreturn total; // Resultado depende de estado externo}Cómo responder en entrevista:
“Una función pura retorna siempre el mismo resultado para los mismos argumentos y no tiene efectos secundarios. Son fáciles de testear, predecibles y permiten optimizaciones como memoización. Los componentes de React deben comportarse como funciones puras respecto a sus props.”
9. ¿Qué es una IIFE?
Section titled “9. ¿Qué es una IIFE?”Definición profesional: Immediately Invoked Function Expression: función que se define y ejecuta inmediatamente, creando un scope privado.
// IIFE clásica - crea scope privado(function() {const privado = "No contamina el global";console.log("Ejecuta inmediatamente");})();
// Con arrow function(() => {console.log("También funciona");})();Cómo responder en entrevista:
“IIFE crea un scope privado para evitar contaminar el namespace global. Era el patrón estándar antes de ES6 modules. Hoy es menos común, pero aún útil en scripts de inicialización y patrones de módulo sin bundler.”
10. ¿Qué es el strict mode?
Section titled “10. ¿Qué es el strict mode?”Definición profesional:
Modo estricto activado con "use strict" que convierte errores silenciosos en excepciones y prohíbe sintaxis problemática.
"use strict";
x = 10; // ReferenceError: x is not defineddelete Object.prototype; // TypeErrorlet private = 1; // SyntaxError (palabra reservada)
// Los módulos ES6 (import/export) tienen strict mode por defectoCómo responder en entrevista:
“Strict mode prohíbe usar variables sin declarar, eliminar propiedades no eliminables, usar palabras reservadas y otras malas prácticas. Los módulos ES6 tienen strict mode activado por defecto. Mejora la seguridad y detección temprana de errores.”
11. ¿Qué es NaN?
Section titled “11. ¿Qué es NaN?”Definición profesional:
Not a Number: valor de tipo number que representa un resultado matemático inválido. Única primitiva en JS que no es igual a sí misma.
console.log(0 / 0); // NaNconsole.log(parseInt('abc')); // NaNconsole.log(typeof NaN); // "number" (quirk histórico)console.log(NaN === NaN); // false (única primitiva así)
// Verificar correctamenteconsole.log(Number.isNaN(NaN)); // true (recomendado)console.log(Number.isNaN("string")); // false (más preciso)console.log(isNaN("string")); // true (hace coerción, menos preciso)Cómo responder en entrevista:
“
NaNes de tiponumbery es el único valor que no es igual a sí mismo. Siempre usoNumber.isNaN()en lugar deisNaN()porque el global hace coerción de tipos y puede dar falsos positivos.NaNse produce en operaciones inválidas como0/0o parsear strings no numéricos.”
12. ¿Cómo verificar si una variable es un array?
Section titled “12. ¿Cómo verificar si una variable es un array?”Definición profesional:
Array.isArray() es el método canónico. instanceof puede fallar en contextos multi-frame. typeof siempre retorna 'object' para arrays.
const arr = [1, 2, 3];
Array.isArray(arr); // true ✅ recomendadoarr instanceof Array; // true (falla en multi-frame)typeof arr; // "object" ❌ no funciona
// Verificar array vacíoArray.isArray(arr) && arr.length === 0; // falseCómo responder en entrevista:
“Siempre uso
Array.isArray(): es el método estándar, funciona en todos los contextos incluyendo iframes con diferentes realms.instanceof Arraypuede fallar porque cada frame tiene su propioArray.typeofretorna'object'para arrays, nulo e inútil para este propósito.”
13. ¿Qué es type coercion?
Section titled “13. ¿Qué es type coercion?”Definición profesional: Conversión automática (implícita) o manual (explícita) entre tipos de datos. La coerción implícita es una fuente común de bugs en JavaScript.
// Coerción implícita - puede ser confusaconsole.log("5" + 3); // "53" (+ concatena si hay string)console.log("5" - 3); // 2 (- convierte a número)console.log(true + 1); // 2console.log([] + []); // "" (arrays a strings)
// Coerción explícita - siempre preferidaNumber("5"); // 5String(5); // "5"Boolean(0); // falseCómo responder en entrevista:
“La coerción implícita convierte tipos automáticamente, lo que causa bugs sutiles.
+con un string concatena;-,*,/convierten a número. Siempre prefiero coerción explícita conNumber(),String(),Boolean(). Uso===en lugar de==para evitar coerción en comparaciones.”
14. ¿Qué son los template literals?
Section titled “14. ¿Qué son los template literals?”Definición profesional:
Strings delimitados con backticks que soportan interpolación de expresiones con ${...} y strings multilínea nativamente.
const nombre = "Juan";const edad = 25;
const mensaje = `Hola, soy ${nombre} y tengo ${edad} años`;
// Multilíneaconst html = `<div> <h1>${nombre}</h1></div>`;
// Expresionesconst precio = `Total: ${(100 * 1.21).toFixed(2)}€`;Cómo responder en entrevista:
“Los template literals usan backticks y permiten interpolación con
${}donde puede ir cualquier expresión JS. Soportan multilínea sin\\nni concatenación. Los tagged templates son una extensión avanzada: permiten procesar el string (base de librerías comostyled-componentsosql).“
15. ¿Qué es destructuring?
Section titled “15. ¿Qué es destructuring?”Definición profesional: Sintaxis ES6 para extraer valores de arrays u objetos en variables individuales. Soporta valores por defecto, alias y rest.
// Array destructuringconst [a, b, ...resto] = [1, 2, 3, 4, 5];// a=1, b=2, resto=[3,4,5]
// Object destructuring con alias y defaultconst { nombre: n, edad = 18, ciudad = "Lima" } = { nombre: "Juan" };// n="Juan", edad=18, ciudad="Lima"
// En parámetros de funciónfunction mostrar({ nombre, edad }) {console.log(`${nombre} tiene ${edad} años`);}Cómo responder en entrevista:
“Destructuring extrae valores de arrays y objetos en una sola línea. Soporta valores por defecto, renombrar variables con alias y rest pattern para agrupar el resto. Es omnipresente en React: destructuring de props, hooks (
const [state, setState] = useState()), imports y respuestas de APIs.”
16. ¿Qué es this?
Section titled “16. ¿Qué es this?”Definición profesional:
this referencia el contexto de ejecución actual. En funciones normales es dinámico (depende de cómo se llama). En arrow functions es léxico (hereda del scope padre).
const obj = {nombre: "Juan",saludarNormal() { console.log(this.nombre); }, // "Juan"saludarArrow: () => console.log(this?.nombre), // undefined (léxico)};
// En función normal fuera de objetofunction mostrar() { console.log(this); } // window en browser, undefined en strictCómo responder en entrevista:
“
thisen funciones normales se determina en tiempo de ejecución según quién llama la función. En arrow functions es léxico: heredathisdel scope donde fue definida, nunca tiene el suyo propio. En clases siempre referencia la instancia.call,applyybindpermiten controlarthisexplícitamente.”
17. ¿Qué son call, apply y bind?
Section titled “17. ¿Qué son call, apply y bind?”Definición profesional:
Tres métodos de Function.prototype para controlar explícitamente el valor de this. call y apply ejecutan inmediatamente; bind retorna una nueva función con this fijo.
function saludar(saludo, signo) {console.log(`${saludo}, ${this.nombre}${signo}`);}const persona = { nombre: "Juan" };
saludar.call(persona, "Hola", "!"); // args separadossaludar.apply(persona, ["Hola", "!"]); // args en arrayconst fn = saludar.bind(persona, "Hola"); // nueva función con this fijofn("!");Cómo responder en entrevista:
“
callejecuta conthisy argumentos separados.applyigual pero con array de args (útil con spread:Math.max.apply(null, arr)).bindretorna una nueva función conthispermanentemente fijo, ideal para callbacks y event handlers. En ES6+, las arrow functions suelen reemplazar la necesidad debind.”
18. ¿Qué es el prototype?
Section titled “18. ¿Qué es el prototype?”Definición profesional: Objeto del que heredan propiedades y métodos los objetos creados con una función constructora. Es el mecanismo de herencia en JavaScript.
function Persona(nombre) { this.nombre = nombre; }
Persona.prototype.saludar = function() {console.log(`Hola, soy ${this.nombre}`);};
const juan = new Persona("Juan");juan.saludar(); // "Hola, soy Juan"juan.__proto__ === Persona.prototype; // trueCómo responder en entrevista:
“El prototype es el objeto del que heredan los objetos JavaScript. Cuando accedes a una propiedad, JS la busca primero en el objeto, luego en su prototype, y así hasta
null(cadena de prototipos). Las clases ES6 son azúcar sintáctica sobre este mecanismo. Compartir métodos en el prototype ahorra memoria frente a definirlos en el constructor.”
19. ¿Qué es la herencia prototípica?
Section titled “19. ¿Qué es la herencia prototípica?”Definición profesional:
Mecanismo donde los objetos heredan directamente de otros objetos a través de la cadena de prototipos ([[Prototype]]). Las clases ES6 son azúcar sintáctico sobre este sistema.
class Animal {constructor(nombre) { this.nombre = nombre; }hablar() { console.log(`${this.nombre} hace un sonido`); }}
class Perro extends Animal {hablar() { console.log(`${this.nombre} ladra`); }}
const p = new Perro("Rex");p.hablar(); // "Rex ladra"p instanceof Animal; // trueCómo responder en entrevista:
“La herencia prototípica encadena objetos: cada objeto tiene un
[[Prototype]]que forma la cadena hastanull. Las clases ES6 conextendsson azúcar sintáctico sobreObject.create(). A diferencia de la herencia clásica, es más dinámica: se puede modificar el prototype en runtime, aunque no es buena práctica.”
20. ¿Qué es Object.freeze vs Object.seal?
Section titled “20. ¿Qué es Object.freeze vs Object.seal?”Definición profesional:
Dos métodos para restringir mutabilidad. freeze congela completamente el objeto; seal permite modificar propiedades existentes pero no agregar ni eliminar.
| Método | Agregar | Modificar | Eliminar |
|---|---|---|---|
freeze | ❌ | ❌ | ❌ |
seal | ❌ | ✅ | ❌ |
| Normal | ✅ | ✅ | ✅ |
const obj = { a: 1 };Object.freeze(obj);obj.a = 10; // Silenciosamente ignorado (o TypeError en strict)obj.b = 2; // Ignorado
const obj2 = { a: 1 };Object.seal(obj2);obj2.a = 10; // OK - modificar existenteobj2.b = 2; // Ignorado - no agregarCómo responder en entrevista:
“
freezehace el objeto completamente inmutable (shallow).sealpermite modificar valores pero no la estructura. Ambos son shallow: los objetos anidados no se ven afectados. Para inmutabilidad profunda necesitostructuredClone+freezerecursivo o librerías como Immer.”
21. ¿Cómo clonar un objeto?
Section titled “21. ¿Cómo clonar un objeto?”Definición profesional:
Shallow copy copia el primer nivel (los anidados siguen siendo referencias). Deep copy copia toda la estructura. structuredClone() es el método moderno recomendado para deep copy.
const original = { a: 1, b: { c: 2 } };
// Shallow copy - objetos anidados son referencias compartidasconst shallow1 = { ...original };const shallow2 = Object.assign({}, original);
// Deep copy - copia completa e independienteconst deep1 = structuredClone(original); // Moderno ✅const deep2 = JSON.parse(JSON.stringify(original)); // Limitado: no funciones, no DateCómo responder en entrevista:
“Para shallow copy uso spread
{...obj}uObject.assign(). Para deep copy usostructuredClone()(ES2022, soporta Date, Map, Set, RegExp).JSON.parse(JSON.stringify())es el clásico pero pierde funciones,undefined,Date(se convierte a string) y referencias circulares.”
22. ¿Qué es el optional chaining?
Section titled “22. ¿Qué es el optional chaining?”Definición profesional:
Operador ?. que cortocircuita y retorna undefined si algún nodo de la cadena es null o undefined, en lugar de lanzar un error.
const usuario = { nombre: "Juan", direccion: { ciudad: "Lima" } };
// Sin optional chainingconst pais = usuario.direccion && usuario.direccion.pais;
// Con optional chaining ✅const pais2 = usuario.direccion?.pais; // undefinedconst metodo = usuario.saludar?.(); // undefinedconst valor = arr?.[0]?.nombre; // acceso dinámicoCómo responder en entrevista:
“
?.cortocircuita y retornaundefinedsi el valor esnulloundefined. Funciona en tres formas:obj?.prop,obj?.[expr]yfunc?.(). Combinado con??es muy potente:usuario?.config?.timeout ?? 3000. Es una de las mejoras más usadas del JavaScript moderno.”
23. ¿Qué es el nullish coalescing?
Section titled “23. ¿Qué es el nullish coalescing?”Definición profesional:
Operador ?? que retorna el operando derecho solo cuando el izquierdo es null o undefined, a diferencia de || que reacciona a cualquier valor falsy.
// || considera falsy: 0, "", false, null, undefinedconst a = 0 || "default"; // "default" (indeseado si 0 es válido)const b = "" || "default"; // "default" (indeseado si "" es válido)
// ?? solo considera null y undefinedconst c = 0 ?? "default"; // 0 ✅const d = "" ?? "default"; // "" ✅const e = null ?? "default"; // "default" ✅Cómo responder en entrevista:
“
??solo hace fallback paranullyundefined, no para todos los valores falsy. Esto es crucial cuando0,falseo''son valores legítimos. Se combina con?.:config?.timeout ?? 3000.??=es el operador de asignación nullish (ES2021):x ??= defaultValue.”
24. ¿Qué son los getters y setters?
Section titled “24. ¿Qué son los getters y setters?”Definición profesional:
Métodos especiales declarados con get/set que interceptan el acceso y escritura a propiedades, permitiendo lógica de validación o transformación transparente.
const persona = {_nombre: "",get nombre() { return this._nombre.toUpperCase();},set nombre(valor) { if (typeof valor !== 'string') throw new Error('Debe ser string'); this._nombre = valor.trim();}};
persona.nombre = " juan ";console.log(persona.nombre); // "JUAN"Cómo responder en entrevista:
“Los getters y setters permiten encapsular lógica detrás de accesos a propiedades. Con
getpuedo computar valores al vuelo; consetpuedo validar y transformar antes de guardar. Son transparentes para el consumidor: se usan como propiedades normales. La clase Vue 2 los usaba para hacer propiedades reactivas.”
25. ¿Qué es un Symbol?
Section titled “25. ¿Qué es un Symbol?”Definición profesional: Tipo primitivo ES6 que genera identificadores únicos e inmutables. Ideal para claves de propiedades que no deben colisionar ni aparecer en iteraciones normales.
const id = Symbol('id');const id2 = Symbol('id');console.log(id === id2); // false - siempre únicos
const obj = { [id]: 123, nombre: "Juan" };console.log(obj[id]); // 123console.log(Object.keys(obj)); // ["nombre"] - Symbol no aparececonsole.log(Symbol.iterator); // Symbol.iterator - well-known symbolCómo responder en entrevista:
“Los Symbols son siempre únicos aunque tengan la misma descripción. Se usan como claves de propiedades privadas (no aparecen en
for...inniObject.keys()). Los well-known symbols comoSymbol.iterator,Symbol.toPrimitivepermiten customizar comportamientos del lenguaje.”
26. ¿Qué es un Map vs Object?
Section titled “26. ¿Qué es un Map vs Object?”Definición profesional:
Map es una colección ordenada de pares clave-valor donde las claves pueden ser de cualquier tipo. Object solo acepta strings y symbols como claves.
| Característica | Map | Object |
|---|---|---|
| Tipo de clave | Cualquiera | String/Symbol |
| Orden | Inserción garantizada | No garantizado |
| Tamaño | .size | Object.keys().length |
const map = new Map();map.set({ id: 1 }, "objeto como clave");map.set(42, "número como clave");map.size; // 2
// Object - convierte la clave a stringconst obj = {};obj[{ id: 1 }] = "valor"; // clave "[object Object]"Cómo responder en entrevista:
“Uso
Mapcuando necesito claves que no sean strings (funciones, objetos), cuando el orden importa, o cuando necesito iterar frecuentemente confor...of.Maptambién tiene mejor rendimiento para colecciones grandes.Objectes mejor para datos con estructura conocida y acceso por clave string.”
27. ¿Qué es un Set?
Section titled “27. ¿Qué es un Set?”Definición profesional: Colección de valores únicos donde la búsqueda, inserción y eliminación son O(1). Ideal para eliminar duplicados y operaciones de conjuntos.
const set = new Set([1, 2, 2, 3, 3, 3]);console.log([...set]); // [1, 2, 3]
set.add(4);set.has(2); // true - O(1)set.delete(1);
// Eliminar duplicados de arrayconst unique = [...new Set([1,1,2,2,3])]; // [1,2,3]
// Intersecciónconst a = new Set([1,2,3]);const b = new Set([2,3,4]);const interseccion = new Set([...a].filter(x => b.has(x)));Cómo responder en entrevista:
“
Setalmacena valores únicos con búsqueda O(1). El uso más común es eliminar duplicados de un array con[...new Set(arr)]. También sirve para operaciones de conjuntos: unión, intersección, diferencia.WeakSetes la versión con referencias débiles (solo objetos, no iterable).“
28. ¿Qué es un WeakMap y WeakSet?
Section titled “28. ¿Qué es un WeakMap y WeakSet?”Definición profesional: Versiones con referencias débiles de Map y Set. Las claves deben ser objetos; cuando el objeto no tiene más referencias, el garbage collector puede eliminarlo automáticamente.
const cache = new WeakMap();
function procesar(obj) {if (cache.has(obj)) return cache.get(obj);const resultado = /* cálculo costoso */ obj;cache.set(obj, resultado);return resultado;}
let datos = { valores: [1,2,3] };procesar(datos);datos = null; // El entry en WeakMap se limpia automáticamenteCómo responder en entrevista:
“
WeakMapyWeakSettienen referencias débiles: cuando el objeto-clave ya no tiene referencias fuertes, el GC lo elimina y el entry desaparece. No son iterables ni tienensize. Ideales para caches asociados a objetos (memoización, datos privados de instancias) sin causar memory leaks.”
29. ¿Qué es un Proxy?
Section titled “29. ¿Qué es un Proxy?”Definición profesional: Objeto que intercepta operaciones sobre otro objeto mediante traps. Es la base de la reactividad en Vue 3 y permite metaprogramación.
const handler = {get(target, prop) { return prop in target ? target[prop] : 'Propiedad no existe';},set(target, prop, value) { if (typeof value !== 'number') throw new TypeError('Solo números'); target[prop] = value; return true;}};
const proxy = new Proxy({}, handler);proxy.edad = 25; // OKproxy.edad = "25"; // TypeErrorCómo responder en entrevista:
“
Proxyenvuelve un objeto e intercepta operaciones con traps:get,set,has,deleteProperty,apply, etc. Vue 3 usa Proxies para reactividad (Vue 2 usabaObject.defineProperty, más limitado). Útil para validación, logging, valores por defecto y objetos reactivos.”
30. ¿Qué es Reflect?
Section titled “30. ¿Qué es Reflect?”Definición profesional:
API con métodos estáticos que replican el comportamiento de los operadores del lenguaje. Diseñada para complementar Proxy, delegar operaciones y retornar booleanos en lugar de lanzar errores.
const obj = { a: 1 };
Reflect.get(obj, 'a'); // 1 (como obj.a)Reflect.set(obj, 'b', 2); // trueReflect.has(obj, 'a'); // true (como 'a' in obj)Reflect.deleteProperty(obj, 'a'); // true
// Uso en Proxy - delegar al comportamiento originalconst proxy = new Proxy(obj, {get(target, prop) { return Reflect.get(target, prop); // delega al target}});Cómo responder en entrevista:
“
Reflectproporciona métodos funcionales equivalentes a operadores del lenguaje. Es el complemento deProxy: dentro de los traps,Reflectpermite delegar al comportamiento original del objeto. Retorna booleanos en lugar de lanzar errores, lo que facilita el manejo de fallos.”
31. ¿Qué es un callback?
Section titled “31. ¿Qué es un callback?”Definición profesional: Función pasada como argumento a otra función para ser invocada en un momento posterior, ya sea de forma síncrona o asíncrona.
function obtenerDatos(callback) {setTimeout(() => callback({ nombre: "Juan" }), 1000);}
obtenerDatos((data) => console.log(data));
// Callbacks síncronos también existen:[1, 2, 3].forEach(n => console.log(n)); // callback síncronoCómo responder en entrevista:
“Un callback es cualquier función pasada como argumento para ejecutarse después. Pueden ser síncronos (
forEach,map) o asíncronos (setTimeout, eventos). El problema es el callback hell cuando se anidan operaciones asíncronas. Hoy usamos Promises y async/await para código asíncrono más legible.”
32. ¿Qué es callback hell?
Section titled “32. ¿Qué es callback hell?”Definición profesional: Anidación excesiva de callbacks asíncronos que forma una “pirámide del destino”, dificultando la lectura, el manejo de errores y el mantenimiento.
// Callback hell - pirámide del destinoobtenerUsuario(id, (usuario) => {obtenerPedidos(usuario.id, (pedidos) => { obtenerDetalles(pedidos[0].id, (detalles) => { // ... más niveles });});});
// Solución con async/awaitconst usuario = await obtenerUsuario(id);const pedidos = await obtenerPedidos(usuario.id);const detalles = await obtenerDetalles(pedidos[0].id);Cómo responder en entrevista:
“El callback hell surge al anidar múltiples callbacks asíncronos, creando código difícil de leer y con manejo de errores por cada nivel. La solución son Promises con
.then()encadenado, pero la mejor solución esasync/awaitque permite código asíncrono con apariencia síncrona y un solotry/catch.”
33. ¿Cuáles son los estados de una Promise?
Section titled “33. ¿Cuáles son los estados de una Promise?”Definición profesional:
Una Promise tiene tres estados: pending (inicial), fulfilled (resuelta con valor) y rejected (rechazada con error). La transición es irreversible.
const promise = new Promise((resolve, reject) => {// Estado: pending...setTimeout(() => { if (Math.random() > 0.5) { resolve("éxito"); // Estado: fulfilled } else { reject("error"); // Estado: rejected }}, 1000);});
promise.then(valor => console.log("Fulfilled:", valor)).catch(error => console.log("Rejected:", error));Cómo responder en entrevista:
“Una Promise tiene tres estados:
pending(esperando),fulfilled(resuelta con.then()) yrejected(rechazada con.catch()). Una vez que sale dependingno puede volver a cambiar..finally()se ejecuta siempre. Los estados son la base para entenderPromise.all,race,allSettledyany.”
34. ¿Qué es Promise.all?
Section titled “34. ¿Qué es Promise.all?”Definición profesional: Ejecuta múltiples promises en paralelo y retorna una nueva promise que se resuelve cuando TODAS resuelven. Si una falla, rechaza inmediatamente.
// Paralelo: todas empiezan a la vezconst [users, posts, comments] = await Promise.all([fetch('/api/users').then(r => r.json()),fetch('/api/posts').then(r => r.json()),fetch('/api/comments').then(r => r.json()),]);// Si cualquiera falla, el catch captura el primer errorCómo responder en entrevista:
“
Promise.allejecuta en paralelo y espera a que todas resuelvan. Si UNA falla, falla todo inmediatamente (fail-fast). Úsalo cuando necesitas todos los resultados para continuar. Si quieres manejar fallos individuales, usaPromise.allSettled. El orden del array resultado siempre corresponde al orden de las promises.”
35. ¿Qué es Promise.race?
Section titled “35. ¿Qué es Promise.race?”Definición profesional: Retorna la primera promise en completarse (exitosa o fallida). Ideal para implementar timeouts.
// Implementar timeout con Promise.raceconst timeout = (ms) => new Promise((_, reject) =>setTimeout(() => reject(new Error('Timeout')), ms));
const resultado = await Promise.race([fetch('/api/data'),timeout(5000)]);Cómo responder en entrevista:
“
Promise.raceretorna la primera en resolverse o rechazarse. Su uso principal es implementar timeouts: compito la operación real contra unsetTimeoutque rechaza. A diferencia dePromise.any,racetambién cuenta los rechazos como ganadores.”
36. ¿Qué es Promise.allSettled?
Section titled “36. ¿Qué es Promise.allSettled?”Definición profesional: Espera a que TODAS las promises terminen independientemente del resultado, retornando un array con el estado y valor/razón de cada una.
const resultados = await Promise.allSettled([Promise.resolve(1),Promise.reject('error'),Promise.resolve(3)]);
// [// { status: 'fulfilled', value: 1 },// { status: 'rejected', reason: 'error' },// { status: 'fulfilled', value: 3 }// ]const exitosas = resultados.filter(r => r.status === 'fulfilled');Cómo responder en entrevista:
“
Promise.allSettledespera a que todas terminen sin importar si fallan. Retorna objetos{ status, value }o{ status, reason }. Úsalo cuando quieres procesar todos los resultados aunque algunos fallen: envío de notificaciones batch, operaciones independientes entre sí.”
37. ¿Qué es Promise.any?
Section titled “37. ¿Qué es Promise.any?”Definición profesional:
Retorna la primera promise que se resuelva exitosamente, ignorando los rechazos. Solo falla si TODAS las promises son rechazadas (lanza AggregateError).
// Retorna la primera en tener ÉXITO (ignora rechazos)const primera = await Promise.any([Promise.reject('error1'),Promise.resolve('éxito'), // Esta ganaPromise.reject('error2')]);// 'éxito'
// Solo falla si TODAS fallantry {await Promise.any([Promise.reject('a'), Promise.reject('b')]);} catch (e) {console.log(e instanceof AggregateError); // true}Cómo responder en entrevista:
“
Promise.anyretorna la primera en tener éxito, ignorando rechazos. Solo falla conAggregateErrorcuando todas fallan. Úsalo para obtener el resultado más rápido de varias fuentes alternativas (varios servidores CDN, múltiples APIs de fallback). Es la diferencia conraceque también acepta rechazos.”
38. ¿Cómo manejar errores en async/await?
Section titled “38. ¿Cómo manejar errores en async/await?”Definición profesional:
Con try/catch para capturar tanto errores síncronos como rechazos de promises. El catch recibe el error del reject().
async function obtenerDatos() {try { const response = await fetch('/api/data'); if (!response.ok) throw new Error(`HTTP ${response.status}`); return await response.json();} catch (error) { console.error('Error:', error.message); throw error; // Re-lanzar para el llamador}}
// Alternativa: .catch() al finalobtenerDatos().catch(console.error);Cómo responder en entrevista:
“Uso
try/catchalrededor delawait. Importante:fetchno rechaza en errores HTTP (404, 500), solo en errores de red. Debo verificarresponse.ok. Un error común es no re-lanzar el error si el llamador también necesita manejarlo.finallyse usa para limpieza (cerrar loaders, liberar recursos).“
39. ¿Qué son los microtasks y macrotasks?
Section titled “39. ¿Qué son los microtasks y macrotasks?”Definición profesional: Dos colas del event loop con distinta prioridad. Los microtasks (Promises) se vacían completamente antes de cada macrotask (setTimeout).
console.log('1');setTimeout(() => console.log('2'), 0); // MacrotaskPromise.resolve().then(() => console.log('3')); // Microtaskconsole.log('4');
// Salida: 1, 4, 3, 2// Orden: síncrono → microtasks → macrotaskCómo responder en entrevista:
“El event loop procesa: primero el código síncrono, luego vacía TODOS los microtasks (Promises, queueMicrotask, MutationObserver), luego un macrotask (setTimeout, setInterval, I/O), y repite. Por eso
Promise.resolve().then()siempre ejecuta antes quesetTimeout(fn, 0). Es clave para entender el orden de ejecución en JS.”
40. ¿Qué es un generator?
Section titled “40. ¿Qué es un generator?”Definición profesional:
Función especial function* que puede pausar su ejecución con yield y reanudarla con .next(). Retorna un iterador que consume valores lazy.
function* secuencia() {yield 1;yield 2;yield 3;}
const gen = secuencia();gen.next(); // { value: 1, done: false }gen.next(); // { value: 2, done: false }gen.next(); // { value: 3, done: false }gen.next(); // { value: undefined, done: true }
// Secuencia infinitafunction* ids() { let i = 1; while(true) yield i++; }const idGen = ids();idGen.next().value; // 1Cómo responder en entrevista:
“Los generators pausan con
yieldy reanudan con.next(). Son la base de la evaluación lazy: pueden representar secuencias infinitas sin consumir memoria.redux-sagalos usa para manejar side effects.async/awaitfue inspirado en generators + promises.”
41. ¿Cómo seleccionar elementos del DOM?
Section titled “41. ¿Cómo seleccionar elementos del DOM?”Definición profesional:
API del DOM para obtener referencias a nodos HTML. querySelector/querySelectorAll son los métodos modernos y flexibles.
// Recomendados - aceptan selectores CSSdocument.querySelector('.clase'); // Primer matchdocument.querySelectorAll('div.item'); // NodeList (estática)
// Clásicos - por tipo específicodocument.getElementById('mi-id'); // Más rápido por IDdocument.getElementsByClassName('clase'); // HTMLCollection (viva)Cómo responder en entrevista:
“Prefiero
querySelectoryquerySelectorAllpor su flexibilidad con selectores CSS.getElementByIdes más rápido para IDs. La diferencia entreNodeList(estática, dequerySelectorAll) yHTMLCollection(viva, se actualiza automáticamente) es importante: con HTMLCollection si agrego elementos al DOM, la colección cambia.”
42. ¿Qué es event bubbling y capturing?
Section titled “42. ¿Qué es event bubbling y capturing?”Definición profesional:
Dos fases de propagación de eventos en el árbol DOM. Capturing baja de window al target; Bubbling sube del target a window.
// Por defecto: bubbling (false o ausente)element.addEventListener('click', handler); // Bubblingelement.addEventListener('click', handler, false); // Bubblingelement.addEventListener('click', handler, true); // Capturing
// Detener propagaciónevent.stopPropagation(); // Detiene subida/bajadaevent.stopImmediatePropagation(); // Detiene también otros listenersCómo responder en entrevista:
“Los eventos tienen tres fases: capturing (window → target), target y bubbling (target → window). Por defecto los listeners usan bubbling. Capturing se activa con
truecomo tercer argumento.stopPropagation()detiene la propagación. Event delegation aprovecha el bubbling para manejar eventos de hijos en el padre.”
43. ¿Qué es event delegation?
Section titled “43. ¿Qué es event delegation?”Definición profesional:
Patrón que registra un solo listener en el elemento padre y usa event.target para identificar qué hijo disparó el evento. Aprovecha el bubbling.
// Un listener para todos los <li>, incluso los agregados despuésdocument.querySelector('ul').addEventListener('click', (e) => {if (e.target.matches('li.item')) { console.log('Click en:', e.target.dataset.id);}});
// Agregar nuevo elemento - el listener ya lo cubreconst nuevoItem = document.createElement('li');nuevoItem.className = 'item';document.querySelector('ul').appendChild(nuevoItem);Cómo responder en entrevista:
“Event delegation pone un listener en el padre y usa
event.target+matches()para identificar el hijo. Dos ventajas: mejor rendimiento (1 listener vs N) y maneja elementos dinámicos que aún no existían al registrar el listener. Es el patrón base de los frameworks: React usa un solo listener en el root.”
44. ¿Cuál es la diferencia entre preventDefault y stopPropagation?
Section titled “44. ¿Cuál es la diferencia entre preventDefault y stopPropagation?”Definición profesional:
preventDefault() cancela la acción nativa del navegador. stopPropagation() cancela la propagación del evento por el árbol DOM. Son independientes.
// preventDefault - cancela la acción del navegadorform.addEventListener('submit', (e) => {e.preventDefault(); // No envía el form (hace fetch en su lugar)});
link.addEventListener('click', (e) => {e.preventDefault(); // No navega a href});
// stopPropagation - detiene la propagaciónbutton.addEventListener('click', (e) => {e.stopPropagation(); // El click no llega al padre});Cómo responder en entrevista:
“
preventDefault()cancela el comportamiento nativo del navegador (navegar, enviar form, menú contextual).stopPropagation()detiene la propagación por el DOM. Son independientes: puedo usar uno, otro, ambos o ninguno.return falseen jQuery hacía ambos, pero en JavaScript nativo solo cancela el handler.”
45. ¿Qué es el localStorage y sessionStorage?
Section titled “45. ¿Qué es el localStorage y sessionStorage?”Definición profesional:
APIs de almacenamiento del navegador. localStorage persiste indefinidamente; sessionStorage se borra al cerrar la pestaña. Solo almacenan strings.
| localStorage | sessionStorage | |
|---|---|---|
| Persistencia | Hasta borrado manual | Cierre de pestaña |
| Compartido | Entre pestañas | Solo esa pestaña |
localStorage.setItem('user', JSON.stringify({ nombre: 'Juan' }));const user = JSON.parse(localStorage.getItem('user'));localStorage.removeItem('user');
sessionStorage.setItem('temp', 'datos temporales');
// Escuchar cambios (solo detecta cambios de otras pestañas)window.addEventListener('storage', (e) => {console.log('Cambio:', e.key, e.newValue);});Cómo responder en entrevista:
“
localStoragepersiste entre sesiones,sessionStoragesolo dura la pestaña. Ambos solo almacenan strings: siempre usoJSON.stringify/JSON.parsepara objetos. Para datos sensibles nunca uso localStorage (vulnerable a XSS). Para autenticación prefiero cookies httpOnly. El eventostoragepermite sincronizar entre pestañas.”
46. ¿Qué es debounce?
Section titled “46. ¿Qué es debounce?”Definición profesional: Técnica de optimización que retrasa la ejecución de una función hasta que transcurre un período de inactividad. Cancela y reinicia el timer en cada llamada.
function debounce(func, delay) {let timeoutId;return function(...args) { clearTimeout(timeoutId); // Cancelar el timer anterior timeoutId = setTimeout(() => func.apply(this, args), delay);};}
// Búsqueda: espera a que el usuario deje de escribirconst buscar = debounce((query) => fetch('/api/search?q=' + query), 300);input.addEventListener('input', (e) => buscar(e.target.value));Cómo responder en entrevista:
“Debounce retrasa la ejecución hasta que pasa un tiempo sin nuevas llamadas. Cada llamada cancela el timer anterior. Ideal para búsquedas en tiempo real (espera a que termine de escribir) y autoguardado. La diferencia con throttle: debounce ejecuta al final de la ráfaga, throttle ejecuta periódicamente durante la ráfaga.”
47. ¿Qué es throttle?
Section titled “47. ¿Qué es throttle?”Definición profesional: Técnica que garantiza que una función se ejecute como máximo una vez por intervalo de tiempo, sin importar cuántas veces se llame.
function throttle(func, limit) {let inThrottle;return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); }};}
// Scroll: ejecutar máximo 1 vez cada 100msconst handleScroll = throttle(() => {checkInfiniteScroll();}, 100);window.addEventListener('scroll', handleScroll);Cómo responder en entrevista:
“Throttle garantiza ejecución periódica: máximo 1 vez por intervalo. Ideal para scroll infinito, resize de ventana y tracking del ratón donde quieres respuesta continua pero limitada. Debounce ejecuta al final de la actividad; throttle ejecuta regularmente durante la actividad.”
48. ¿Qué es el Fetch API?
Section titled “48. ¿Qué es el Fetch API?”Definición profesional: API moderna basada en Promises para hacer peticiones HTTP. Reemplaza XMLHttpRequest con una interfaz más limpia y componible.
// GETconst response = await fetch('/api/users');if (!response.ok) throw new Error('HTTP ' + response.status);const data = await response.json();
// POST con bodyconst res = await fetch('/api/users', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ nombre: 'Juan' })});Cómo responder en entrevista:
“
fetch()retorna una Promise que solo rechaza en errores de red, NO en errores HTTP. Siempre verificoresponse.ok(true para códigos 200-299). Dosawait: uno para la respuesta y otro para el body (response.json(),response.text()). Para features avanzadas (interceptors, cancelación) suelo usar axios oAbortController.”
49. ¿Qué son los módulos en JavaScript?
Section titled “49. ¿Qué son los módulos en JavaScript?”Definición profesional: Sistema ES6 nativo para dividir código en archivos con scope propio. Cada módulo tiene su propio scope y debe exportar explícitamente lo que quiere compartir.
// calculadora.js - exportarexport const PI = 3.14159;export function sumar(a, b) { return a + b; }export default class Calculadora {multiply(a, b) { return a * b; }}
// main.js - importarimport Calculadora, { PI, sumar } from './calculadora.js';import * as calc from './calculadora.js';
// Dynamic import (lazy loading)const modulo = await import('./calculadora.js');Cómo responder en entrevista:
“Los módulos ES6 tienen scope propio: las variables no son globales.
exportnamed permite múltiples exports;export defaultes uno por archivo. Los módulos se importan de forma estática (tree-shaking posible) o dinámicaimport()(lazy loading). Están disponibles nativamente en browsers modernos y son la base de bundlers como Webpack/Vite.”
50. ¿Qué es el patrón módulo revelador?
Section titled “50. ¿Qué es el patrón módulo revelador?”Definición profesional: Patrón de diseño que usa una IIFE con closure para crear variables privadas y retornar solo la API pública. Precursor de los módulos ES6.
const contador = (function() {// Privado - no accesible desde fueralet _count = 0;function _validar(n) { return n >= 0; }
// Público - API reveladareturn { incrementar() { _count++; }, decrementar() { if (_validar(_count - 1)) _count--; }, obtener() { return _count; }};})();
contador.incrementar();contador.obtener(); // 1// contador._count // undefined - privadoCómo responder en entrevista:
“El Revealing Module Pattern usa IIFE + closure para encapsulación: las variables internas son privadas y solo se expone la API pública en el objeto retornado. Era el estándar antes de ES6 modules. Hoy los módulos ES6 y las clases con campos privados (
#field) cubren este caso. Aún se ve en código legacy.”