call y apply en JavaScript: Errores principales y cómo evitarlos
¿Alguna vez has mirado código ajeno en JavaScript y has visto construcciones extrañas como func.call(this, arg1, arg2) o func.apply(this, [arg1, arg2])? ¿Y te has preguntado: "¿Cuál es la diferencia realmente?" Si es así, no estás solo. La pregunta "What is the difference between call and apply?" es una de las más populares en Stack Overflow con cientos de miles de visitas. Y no es casualidad.
La confusión entre call y apply es una trampa clásica para principiantes (y no solo). En este artículo no solo explicaremos la teoría. Analizaremos los 5 errores reales más comunes, mostraremos cómo corregirlos y daremos un algoritmo claro que te librará para siempre de la confusión. ¡Allá vamos!
Breve introducción: ¿qué son call y apply?
Antes de sumergirnos en los errores, refresquemos la base. Los métodos call y apply son métodos incorporados de las funciones en JavaScript. Su tarea principal es indicar explícitamente el contexto de llamada (this) para una función. En otras palabras, permiten decir: "Oye, función, imagina que estás trabajando con este objeto".
Sintaxis:
func.call(context, arg1, arg2, ...);func.apply(context, [arg1, arg2, ...]);Diferencia clave:
callrecibe los argumentos separados por comas (lista).applyrecibe los argumentos en forma de array (u objeto similar a un array).
Eso es todo. Esa es la única diferencia. Pero precisamente por esta "nimiedad" surgen la mayoría de los errores. Analicémoslos.
Top 5 errores al trabajar con call y apply
Error n.º 1: Confusión con la lista de argumentos (¡el más común!)
Este es el "rey" de todos los errores. Escribiste una función que espera argumentos uno por uno, pero pasaste un array mediante call. O viceversa.
Ejemplo catastrófico:
function greet(greeting, punctuation) { console.log(greeting + ', ' + this.name + punctuation);}
const user = { name: 'Ana' };
// Error: pasamos un array, pero usamos callgreet.call(user, ['Hola', '!']); // Salida: "Hola,! Ana,undefined" — ¡un completo desastre!¿Por qué ocurre? call espera argumentos uno por uno. Recibió un solo argumento —un array completo— y lo colocó en la variable greeting. punctuation quedó como undefined.
¿Cómo solucionarlo? Usa apply si los datos ya están en un array:
greet.apply(user, ['Hola', '!']); // Salida: "Hola, Ana!" — ¡correcto!O expande el array con el operador spread (enfoque moderno):
greet.call(user, ...['Hola', '!']); // ¡También funciona!Error n.º 2: Olvidar que apply funciona con objetos similares a arrays
Muchos piensan que apply solo acepta arrays reales. En realidad, acepta cualquier objeto similar a un array (array-like object): debe tener la propiedad length y claves numéricas.
Ejemplo:
function sum() { let total = 0; for (let i = 0; i < arguments.length; i++) { total += arguments[i]; } return total;}
// Pasamos no un array, sino un objeto con lengthconst args = { 0: 5, 1: 10, 2: 15, length: 3 };
console.log(sum.apply(null, args)); // Salida: 30 — ¡funciona!Pero ten cuidado: si el objeto no tiene length, apply simplemente lo ignorará. Este es un error común al trabajar con arguments (objeto obsoleto) o con NodeList.
Error n.º 3: Usar call/apply donde basta una llamada simple
A veces los principiantes abusan de