🧠 JavaScript puede ser simple, pero bajo el capó esconde muchas cosas interesantes. Incluso si ya llevas trabajando con el lenguaje más de un año, conocer su mecánica interna, sus complejidades y sus dificultades te ayudará a escribir un código más limpio, predecible y eficiente. Este artículo es una guía detallada de las características clave de JavaScript, que será útil no solo para principiantes, sino también para desarrolladores experimentados.

🚀 Temas que vamos a tratar:
Hoisting (emersión)
Zona muerta temporal
Function Declaration vs Function Expression
Shallow Copy vs Deep Copy (copia superficial y copia profunda)
Object.assign
Slice vs Splice
forEach vs Map
Global Execution Context
Polyfilling (polifillado)
Profunda inmersión en map()
Coerción de tipos (Type Coercion)
🪄 1. Elevación (Hoisting)
Hoisting es uno de los mecanismos de JavaScript más misteriosos para los principiantes. Este es el comportamiento del motor, en el que las declaraciones de variables y funciones parecen "flotar" al comienzo de su alcance.
Esto significa que puedes intentar acceder a una variable o función antes de que se declare realmente, y a veces incluso funcionará:
console.log(a); // undefined
var a = 10;var - aparece e inicializa undefined, mientras que let y const aparecen, pero no se inicializan. Por lo tanto, el siguiente código generará un error:
console.log(b); // ReferenceError
let b = 20;En cuanto a las funciones, aquí la diferencia entre function declaration y function expression es especialmente importante:
console.log(getNum()); // OK
function getNum() { return 42; }
console.log(getArrow()); // TypeError: getArrow is not a function
var getArrow = () => 42;📸 Prompt para foto: "Infografía sobre hoisting en JavaScript, con división de variables var/let/const y function/function expression"
🕳 2. Temporal Dead Zone (TDZ)
La zona muerta temporal es el período en el que la variable ya ha sido declarada (a través de let o const), pero aún no se ha inicializado. En TDZ, cualquier intento de acceder a una variable llama a ReferenceError.
console.log(value); // ReferenceError
let value = 100;Este mecanismo nos protege de errores y hace que el comportamiento del código sea más predecible. TDZ también se aplica a las funciones definidas como const y let.
🧩 3. Function Declaration vs Function Expression
Function Declaration
function greet() {
console.log("Hello!");
}Estas funciones emergen y se pueden llamar en cualquier lugar del ámbito. Esto es útil si la lógica de la función debe estar disponible en todo el script.
Function Expression
const greet = function() {
console.log("Hello!");
}Aquí, la función se vuelve disponible solo después de asignar una variable. Esto es ideal para su uso en cierres o devoluciones de llamada.
📦 4. Shallow Copy vs Deep Copy
Copia superficial (Shallow Copy)
Copia solo el nivel superior de las propiedades del objeto. Los objetos anidados continúan haciendo referencia a las mismas áreas de memoria:
const obj1 = { name: "Olga", address: { city: "Kazan" } };
const obj2 = { ...obj1 };
obj2.address.city = "Ufa";
console.log(obj1.address.city); // "Ufa"Copia profunda (Deep Copy)
Permite copiar completamente el objeto, incluidas las estructuras anidadas:
const deepCopy = structuredClone(obj1);
deepCopy.address.city = "Sochi";Alternativas:
JSON.stringify/parse— no funciona con las funciones yundefinedstructuredClone— método modernoFunción recursiva personalizada
📸 Prompt para foto: "Comparación de la copia superficial y profunda con visualización de objetos incrustados"
🔄 5. Object.assign()
El método permite copiar propiedades de uno o más objetos al destino:
const objA = { name: "Alice" };
const objB = { age: 30 };
const result = Object.assign({}, objA, objB);Características:
Devuelve el objeto de destino
Copia solo sus propias propiedades enumeradas
Sobrescribe propiedades con el mismo nombre
Alternativa: sintaxis de propagación: { ...objA, ...objB }
✂️ 6. Slice vs Splice
slice() y splice() son métodos de matriz que a menudo se confunden entre sí:
slice(start, end)— devuelve una nueva matriz sin cambiar la originalsplice(start, deleteCount, ...items)- cambia la matriz en su lugar
const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(1, 3)); // [2, 3]
console.log(arr.splice(1, 2, 9, 9)); // [2, 3], arr ahora [1, 9, 9, 4, 5]🔁 7. forEach vs map
Ambos métodos recorren la matriz, pero hay matices:
Característica | forEach | map |
|---|---|---|
Devuelve una nueva matriz | ❌ | ✅ |
¿Puedes salir del ciclo? | ❌ | ❌ |
Se utiliza para | Efectos secundarios | Transformaciones |
[1, 2, , 4].map(x => x || 0); // procesamos la matriz dispersaSi necesita detener la ejecución, use for, for...of, some o every.
🌍 8. Global Execution Context
Contexto de ejecución es el entorno en el que se ejecuta el código. Hay dos tipos:
Global - se crea primero, contiene variables globales, funciones y el objeto
this.Funcional — se crea cuando se llama a cada función.
Una vez finalizado el script, se elimina el contexto global.
🛠 9. Polyfilling
Los polifilos permiten emular el comportamiento de las nuevas funciones del lenguaje en los navegadores antiguos.
Ejemplo: polyfill para Array.prototype.includes:
if (!Array.prototype.includes) {
Array.prototype.includes = function(el) {
return this.indexOf(el) !== -1;
};
}Los polifilos son especialmente importantes en el desarrollo de soluciones multiplataforma.
🗺 10. Map Deep Dive
El método map() toma tres argumentos:
valor
código postal
matriz original
const data = [1, 2, , 4];
const result = data.map((val, idx, arr) => val ? val * 2 : (arr[idx - 1] || 1));Características:
Los elementos omitidos (
empty slots) se ignoranLos nuevos elementos añadidos durante la ejecución no se procesan
Eliminados antes de la ejecución: omitidos
⚖️ 11. Type Coercion (Coerción de tipos)
Implícito (implicit):
10 + "2"; // "102"
10 - "2"; // 8
true + 1; // 2
[] + 1; // "1"
null + 1; // 1
undefined + 1; // NaNExplícito (explicit):
String(123);
Number("456");
Boolean(0); // falseEs importante entender cómo y cuándo se produce la conversión para evitar errores inesperados.
📝 Conclusión
📚 Una comprensión profunda del funcionamiento interno de JavaScript te ayudará no solo a escribir código, sino a diseñar la arquitectura de la aplicación de manera más confiable y clara. Esto es especialmente importante en el desarrollo en equipo, donde la legibilidad y la previsibilidad del comportamiento son fundamentales.
Después de analizar temas como hoisting, TDZ, tipos de funciones, copia de objetos, características de map y forEach, así como la conversión de tipos, llegas a un nivel en el que JavaScript deja de ser solo un lenguaje: se convierte en una herramienta para ajustar la lógica.
