Newsletter para devsEntra

15 preguntas resueltas de entrevistas para aprender JavaScript

JavaScript es peculiar y en las entrevistas de trabajo lo saben

Una de las principales ventajas de JavaScript es que es un lenguaje de programación interpretado y de tipado dinámico.

Esto significa que no necesitas compilar el código antes de ejecutarlo, lo que te permite probar y depurar el código de manera más rápida y sencilla.

Otra ventaja importante de JavaScript es que es un lenguaje multiplataforma que se puede utilizar en diferentes entornos, como navegadores web, servidores, dispositivos móviles y sistemas embebidos.

Todo esto hace que JavaScript tenga muchas peculiaridades y algunas acciones que parecen sencillas tienen soluciones curiosas.

Y por eso en las entrevistas de trabajo aprovechan estas oportunidades para saber si dominas el lenguaje o no.

Al final del todo te doy el mejor consejo para aprender bien y profundo cuáles son las respuestas a estas 15 preguntas de entrevista tan populares.

🎧 Podcast relacionado

Te recomiendo escuchar y descubrir 3 consejos para aprender JavaScript que me hubiera gustado escuchar al empezar, un episodio que se “viralizó” gracias a Spotify.

<iframe src="https://widget.spreaker.com/player?episode_id=48338128&amp;theme=light&amp;playlist=false&amp;playlist-continuous=false&amp;autoplay=false&amp;live-autoplay=false&amp;chapters-image=true&amp;episode_image_position=right&amp;hide-logo=true&amp;hide-likes=true&amp;hide-comments=true&amp;hide-sharing=true" width="100%" height="180px" frameborder="0"></iframe>

1. ¿Cómo puedo borrar un elemento específico de un array en JavaScript?

Para borrar un elemento específico de un array en JavaScript, puedes usar el método filter(). Crea un nuevo array con todos los elementos que pasan la prueba implementada por la función proporcionada. Puedes usar este método para crear un nuevo array que no contenga el elemento que deseas borrar.

Lo tenemos aquí:

const numbers = [1, 2, 3, 4, 5];

// Usa el método filter() para crear un nuevo array sin el elemento que quieres borrar
const newNumbers = numbers.filter(number => number !== 3);

// El array newNumbers ahora contiene [1, 2, 4, 5]

En este ejemplo, el método filter() se usa para crear un nuevo array llamado newNumbers que no contiene el número 3.

Usa una función de devolución de llamada para probar cada elemento en el array numbers, y solo incluye elementos que no sean iguales a 3 en el nuevo array.

El método filter() no modifica el array original, simplemente crea un nuevo array con los elementos deseados. Si quieres eliminar el elemento del array original, necesitarás usar un método diferente, como splice().

Alternativa con el método splice

Este método te permite eliminar uno o más elementos de un array en una determinada posición y devuelve los elementos eliminados.
Por ejemplo, supongamos que tienes el siguiente array:

const numbers = [1, 2, 3, 4, 5];

Para eliminar el número 3 de este array, puedes utilizar el método splice() de la siguiente manera:

const removed = numbers.splice(2, 1);

En este ejemplo, se elimina el elemento en la posición 2 (el número 3) del array numbers y se almacena en la variable removed.

Después de ejecutar este código, la variable numbers contendrá el siguiente array:

[1, 2, 4, 5]

Y la variable removed contendrá el siguiente array:

[3]

Si quieres eliminar más de un elemento de un array, puedes especificar un valor mayor que 1 en el segundo parámetro del método splice().

Por ejemplo, si quieres eliminar los números 3 y 4 del array, puedes utilizar el método splice() de la siguiente manera:

const removed = numbers.splice(2, 2);

Se eliminan los dos elementos en las posiciones 2 y 3 (los números 3 y 4) del array numbers y se almacenan en la variable removed.

2. ¿Cómo funcionan las closures en JavaScript?

Las closures en JavaScript son una combinación de una función y el entorno léxico en el que se declaró esa función. Esto significa que una closure tiene acceso a las variables y funciones que están en el ámbito en el momento en que se crea, incluso si la función se ejecuta en un ámbito o contexto diferente.

Mira este código:

function createCounter() {
let count = 0;

	return function() {
		count++;
		console.log(count);
	}
}

const counter1 = createCounter();
const counter2 = createCounter();

counter1(); // muestra 1
counter1(); // muestra 2
counter2(); // muestra 1

En este ejemplo, la función createCounter() crea una closure devolviendo una función anónima que tiene acceso a la variable count. Cuando se ejecuta la función anónima, incrementa la variable count y muestra su valor.

Aunque la función anónima se ejecuta fuera de la función createCounter(), todavía tiene acceso a la variable count porque fue declarada dentro del entorno léxico de la función createCounter().

Esto es lo que permite que las variables counter1 y counter2 mantengan sus propios valores de count separados.

Más aplicaciones prácticas de las closures

Se pueden utilizar en diferentes situaciones prácticas:

Acceso a variables privadas:

const secret = () => {
  const secretValue = "12345";
  return {
    getValue: () => secretValue,
    setValue: (value) => (secretValue = value),
  };
};
const s = secret();
console.log(s.getValue()); // "12345"
s.setValue("67890");
console.log(s.getValue()); // "67890"

En este caso, la función secret retorna un objeto con dos métodos: getValue y setValue. Estos métodos tienen acceso a la variable secretValue, que es una variable privada que no se puede acceder desde el exterior de la función secret. Como resultado, se pueden crear objetos con métodos que tengan acceso a variables privadas.

Sin pérdida de estado.

El otro ejemplo es para funciones que se puedan ejecutar varias veces con diferentes argumentos sin perder el estado de las variables locales:

const calculator = (operation) => {
  let result = 0;
  return (value) => {
    if (operation === "+") {
      result += value;
    } else if (operation === "-") {
      result -= value;
    } else if (operation === "*") {
	  result *= value;
	} else if (operation === "/") {
		result /= value;
	}
	return result;
	};
};

const add = calculator("+");
console.log(add(10)); // 10
console.log(add(20)); // 30
console.log(add(30)); // 60
const sub = calculator("-");
console.log(sub(10)); // -10
console.log(sub(20)); // -30

En este caso, la función calculator retorna una closure que mantiene el estado de la variable result y que puede realizar diferentes operaciones matemáticas en función del parámetro operation que se le pasa cuando se crea la closure. Como resultado, se pueden crear varias closures con la función calculator que realicen operaciones matemáticas distintas sin perder el estado de la variable result.

Mujer programadora en medio de un concierto

3. ¿Cómo se puede comprobar que un string contiene un substring en JavaScript?

Para comprobar si un string contiene un substring en JavaScript, puedes usar el método includes(). Este método toma un string como argumento y devuelve un valor booleano que indica si el string contiene el substring.

Por ejemplo, si tienes un string llamado myString y quieres comprobar si contiene el substring “hello”, puedes usar el siguiente código:

const myString = 'Mister Potato dice hello!';

if (myString.includes("hello")) {
	console.log("myString contiene el substring 'hello'");
} else {
	console.log("myString no contiene el substring 'hello'");
}

Otra forma de comprobar si un string contiene un substring es usar el método indexOf(). Este método devuelve el índice del substring dentro del string, o -1 si no se encuentra el substring.

No me gusta especialmente: A día de hoy, cada vez que lo uso, nunca tengo claro como funciona.

Un ejemplillo más:

const myString = 'Mister Potato dice hello!';

if (myString.indexOf("hello") !== -1) {
	console.log("myString contiene el substring 'hello'");
} else {
	console.log("myString no contiene el substring 'hello'");
}

4. ¿Cómo puedo borrar una propiedad de un objeto de JavaScript?

Para borrar una propiedad de un objeto de JavaScript, puedes usar la palabra clave delete. Esta palabra clave borra la propiedad y su valor del objeto.

Por ejemplo, si tienes un objeto llamado “myObject” con una propiedad llamada “name”, puedes borrar la propiedad:

const myObject = {
	name: 'Perico',
	age: 33,
}

delete myObject.name;

Después de ejecutar este código, el objeto myObject ya no tendrá la propiedad “name”.

👀 Ten en cuenta que la palabra clave delete solo funciona en las propiedades de un objeto y no en las variables ni en los argumentos de una función.

Otra forma alternativa con …rest

Otra forma de borrar una propiedad de un objeto es usar la sintaxis ES6 para la destrucción de objetos. Esto te permite especificar qué propiedades quieres conservar, y se borrarán todas las demás propiedades.

Por ejemplo, si tienes un objeto llamado “myObject” con las propiedades “name” y “age”, puedes borrar la propiedad “age” con el siguiente código:

const { age, ...rest } = myObject;

// myObject no cambia pero "rest" tendrá el resto del objeto, en este caso "name"

5. ¿Cuál es la diferencia entre “let” y “var”?

La principal diferencia entre las palabras clave “let” y “var” en JavaScript es el ámbito (en inglés, scope) en el que las variables que definen son accesibles.

La palabra clave “var” se usa para definir variables que son accesibles en el ámbito de función o global actual.

Esto significa que las variables definidas con “var” pueden ser accedidas y modificadas desde cualquier parte del ámbito de función o global actual.

La palabra clave “let” se usa para definir variables que solo son accesibles dentro del bloque en el que se declaran. Esto significa que las variables “let” solo son accesibles dentro del bloque en el que se declaran, y no en cualquier bloque anidado ni en el ámbito global.

Aquí puedes verlo:

function example() {
	var x = 1;
	let y = 2;
	
	if (x === 1) {
		var x = 3;
		let y = 4;
		console.log(x); // muestra 3
		console.log(y); // muestra 4
	}

	console.log(x); // muestra 3
	console.log(y); // muestra 2
}

Aquí puedes ver como “let” define la variable con un valor diferente en cada ámbito (dentro del “if”) y “var” cambia de valor.

6. ¿Cuál es la diferencia entre “const” y “let”?

La principal diferencia entre las palabras clave “const” y “let” en JavaScript es que las variables declaradas con “const” son constantes y no se pueden reasignar, mientras que las variables “let” pueden reasignarse.

En resumen, que una vez que declaras una variable con “const”, su valor no puede cambiarse y cualquier intento de reasignarla provocará un error.

Las variables declaradas con “let” pueden cambiar sus valores en cualquier momento y pueden reasignarse a diferentes valores.

Fíjate en este código:

const x = 1; 
let y = 2;

x = 2; // lanza un error 
y = 3; // reasigna el valor de y a 3

En general, se recomienda usar “const” para variables que no se pretenden reasignar y “let” para variables que se pueden reasignar más adelante en el código. Esto ayuda a evitar reasignaciones no intencionadas y mejorar la legibilidad del código.

7. ¿Qué operador de igualdad (== o ===) debe usarse en una comparación en JavaScript?

En JavaScript, se recomienda usar el operador de igualdad estricta (===) al comparar valores. Comprueba tanto la igualdad de valor como de tipo, mientras que el operador de igualdad débil (==) solo comprueba la igualdad de valor.

Por ejemplo, consideremos el siguiente código que usa los operadores de igualdad estricta y débil:

const x = 1;
const y = "1";

console.log(x === y); // muestra false
console.log(x == y); // muestra true

En este código, las variables x e y tienen distintos tipos (número y cadena), por lo que el operador de igualdad estricta (===) devuelve false. Sin embargo, el operador de igualdad débil (==) convierte el valor de cadena de y a un número y compara los valores, por lo que devuelve true.

Usar el operador de igualdad estricta puede evitar comportamientos inesperados y hacer que el código sea más predecible y fiable.

8. ¿Cómo se recorre en bucle sobre un array?

Para recorrer un array en JavaScript y realizar una acción en cada elemento, se puede utilizar el método forEach o map.

El método forEach se utiliza para iterar sobre un array y ejecutar una función en cada elemento. Por ejemplo:

let numbers = [1, 2, 3, 4, 5];

numbers.forEach(function(number) {
  console.log(number);
});

Esto imprimiría cada número en la consola, uno por línea.

El método map es similar, pero además de ejecutar una función en cada elemento, devuelve un nuevo array con los valores devueltos por la función. Por ejemplo:

let numbers = [1, 2, 3, 4, 5];

let doubledNumbers = numbers.map(function(number) {
  return number * 2;
});

console.log(doubledNumbers);

Esto imprimiría [2, 4, 6, 8, 10] en la consola.

Aunque no es erróneo usar for si es recomendable ahorrarnos código y estos métodos nos lo permiten.

Mujer programadora de JavaScript

9. ¿Cómo puedo validar una dirección de email?

Para validar una dirección de correo electrónico en puedes utilizar una expresión regular para verificar si el formato de la dirección es válido.

Por ejemplo, la siguiente expresión regular verifica si una dirección de correo electrónico tiene el formato correcto:

/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/

👉 Puedes probar expresiones regulares para emails en regex101.

Puedes utilizar esta expresión regular con el método test() del objeto RegExp para verificar si una dirección de correo electrónico dada es válida:

let email = "name@example.com";
let regex = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

if (regex.test(email)) {
  console.log("La dirección de correo electrónico es válida");
} else {
  console.log("La dirección de correo electrónico no es válida");
}

Es importante tener en cuenta que esta expresión regular solo verifica el formato de la dirección de correo electrónico, pero no verifica si realmente existe.

Para hacer eso, deberías enviar un correo electrónico de verificación a la dirección y verificar si se recibe.

10. ¿Cómo puedo cambiar todas las ocurrencias de una cadena de texto?

Puedes utilizar el método replace() del objeto String.

Supongamos que tienes la siguiente cadena:

const text = "This is a test string. This string has multiple occurrences of the word 'test'.";

Para reemplazar todas las ocurrencias de la palabra “test” con la palabra “example”, puedes utilizar el método replace() de la siguiente manera:

const newText = text.replace(/test/g, "example");

En este ejemplo, la variable newText contendrá la siguiente cadena:

"This is a example string. This string has multiple occurrences of the word 'example'."

También puedes utilizar el método replace() con una función de reemplazo en lugar de una cadena de reemplazo.

const newTextAlt = text.replace(/test/g, function(match) {
	return match.charAt(0).toUpperCase() + match.slice(1);
});

En este ejemplo, la variable newText contendrá la siguiente cadena:

"This is a Test string. This string has multiple occurrences of the word 'Test'."

En general, el método replace() te permite reemplazar todas las ocurrencias de una cadena de texto en una cadena dada de manera rápida y fácil.

11. ¿Cómo hacer una copia profunda de un objeto en JavaScript?

Esta es para nota. Para conseguirlo puedes utilizar el método JSON.parse() junto con JSON.stringify().

Para este objeto:

const original = {
  name: "John Doe",
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA"
  }
};

Para hacer una copia profunda de este objeto, puedes utilizar el método JSON.stringify() para convertir el objeto en una cadena de texto, y luego utilizar JSON.parse() para convertir la cadena de texto en un nuevo objeto:

let copy = JSON.parse(JSON.stringify(original));

La variable copy contendrá una copia profunda del objeto original. Esto significa que cualquier cambio que se realice en el objeto copy no afectará al objeto original, ya que son dos objetos diferentes en la memoria.

Alternativa con Object.assign

También puedes utilizar el método Object.assign() para hacer una copia profunda de un objeto.

let copy = Object.assign({}, original);

Este método creará un nuevo objeto y copiará todas las propiedades del objeto original en el nuevo objeto. Sin embargo, si el objeto original tiene propiedades que son objetos u otros valores que pueden ser mutables, estos valores se copiarán por referencia en lugar de por valor.

Esto significa que si se cambia un valor en el objeto copy, también se cambiará en el objeto original.

Alternativa más moderna con structuredClone

Compatible ya con muchos más navegadores está esta opción poderosa.

La función structuredClone() es una utilidad de JavaScript que permite realizar una copia profunda de un objeto, es decir, copia tanto el objeto original como todos los objetos a los que se hace referencia. Esto es útil cuando se quiere trabajar con una copia de los datos sin modificar el objeto original.

Aquí te dejo dos ejemplos de cómo usar structuredClone():

Ejemplo 1: Clonando un objeto simple

const original = {
  name: 'John',
  age: 30,
  city: 'New York'
};

const clone = structuredClone(original);

console.log(clone);
// Output: { name: 'John', age: 30, city: 'New York' }

// Modificamos el objeto clonado
clone.name = 'Jane';

console.log(clone);
// Output: { name: 'Jane', age: 30, city: 'New York' }

console.log(original);
// Output: { name: 'John', age: 30, city: 'New York' }

En este ejemplo, puedes ver que al modificar el objeto clonado, el objeto original no se ve afectado.

Ejemplo 2: Clonando un objeto con propiedades anidadas

const original = {
  name: 'John',
  age: 30,
  address: {
    city: 'New York',
    country: 'USA'
  }
};

const clone = structuredClone(original);

console.log(clone);
// Output: { name: 'John', age: 30, address: { city: 'New York', country: 'USA' } }

// Modificamos el objeto clonado
clone.address.city = 'Los Angeles';

console.log(clone);
// Output: { name: 'John', age: 30, address: { city: 'Los Angeles', country: 'USA' } }

console.log(original);
// Output: { name: 'John', age: 30, address: { city: 'New York', country: 'USA' } }

En este segundo ejemplo, incluso cuando modificamos una propiedad anidada en el objeto clonado, el objeto original sigue siendo el mismo. Esto demuestra el poder de structuredClone() para realizar copias profundas de objetos.

12. ¿Cómo puedo comprobar si un array incluye un valor?

Vuelve un viejo conocido, el método includes() del objeto Array. Este método devuelve true si el array incluye el valor especificado, y false si no lo incluye.

Pero antes, ¿no lo usábamos en un string?
En efecto, pero es que una cadena de texto en JavaScript tiene muchas similitudes con un array de caracteres.

Vamos a responder a esta pregunta:

const numbers = [1, 2, 3, 4, 5];

Para comprobar si el array numbers incluye el número 3, puedes utilizar el método includes() de la siguiente manera:

if (numbers.includes(3)) {
	console.log("El array incluye el número 3");
}

El método includes() te sirve para comprobar si un array incluye un valor de cualquier tipo, no solo números.

Logo alternativo no oficial de JavaScript

13. ¿Cuál es la razón para utilizar “use script” en JavaScript?

Activarás el modo estricto.

En modo estricto, se aplican un conjunto de reglas más concretas y requeridas a la sintaxis y a la ejecución del código, lo que puede ayudar a evitar errores comunes y mejorar la seguridad del código.

Algunas de las principales ventajas de utilizar use strict en JavaScript son las siguientes:

  • Evita que se declaren variables globales accidentalmente, lo que puede causar conflictos de nombres y errores difíciles de depurar.
  • Prohíbe el uso de variables no declaradas, lo que puede ayudar a evitar errores comunes.
  • Prohíbe la reasignación de la palabra clave eval, lo que puede mejorar la seguridad del código.
  • Evita el uso de expresiones y operadores que pueden dar lugar a errores comunes.
  • Proporciona una sintaxis más clara y concisa para la creación de objetos y la herencia de clases.
  • Para utilizar use strict en un archivo JavaScript, simplemente debes incluir la palabra clave al principio del archivo, como se muestra a continuación:
"use strict";

// Tu código JavaScript va aquí

Es válido dentro de una función, en cuyo caso solo se aplicará en modo estricto dentro de esa función:

function myFunction() {
  "use strict";

  // Tu código JavaScript va aquí
}

14. ¿Cómo generar un timestamp?

Un timestamp en JavaScript es un número que representa la cantidad de milisegundos transcurridos desde el 1 de enero de 1970 00:00:00 UTC. Los timestamps se utilizan a menudo para almacenar y comparar fechas y horas en JavaScript.

Para obtener el timestamp actual en JavaScript, puedes utilizar la propiedad Date.now(). Esta propiedad devuelve el timestamp actual en milisegundos.

const timestamp = Date.now();

console.log(timestamp); // Imprime el timestamp actual en milisegundos

Para convertir un timestamp en una fecha legible, puedes utilizar el objeto Date de JavaScript.

Con el siguiente timestamp:

const timestamp = 1616943813000; // 5 de octubre de 2021, 10:23:33

Para convertir este timestamp en una fecha legible, puedes utilizar el objeto Date así:

const date = new Date(timestamp);

console.log(date.toString()); // Imprime "Fri Oct 05 2021 10:23:33 GMT-0500 (hora de verano central)"

En este ejemplo, se imprime la fecha convertida a un formato de texto por defecto con toString().

También puedes utilizar el objeto Date de JavaScript para obtener el timestamp de una fecha y hora específicas. El objeto Date es muy flexible y puedes generar tu copia incluso con datos específicos:

const date = new Date(2022, 11, 2, 10, 30, 0);
const timestamp = date.getTime();

15. ¿Cómo devuelvo la respuesta de una llamada asíncrona a una API?

Necesitas la sintaxis async/await en JavaScript. Esta sintaxis te permite escribir código asíncrono de una forma similar al código síncrono, lo que lo hace más fácil de leer y entender.

Por ejemplo, consideremos el siguiente código que hace una llamada asíncrona a una API usando la función fetch():

async function getData() {
	const response = await fetch("https://www.example.com/api/data");
	const data = await response.json();
	return data;
}

En este código, la función getData() está marcada como async, lo que indica que devuelve una promesa. Dentro de la función, se hace la llamada fetch() y se espera la respuesta usando la palabra clave await. Luego, se convierte la respuesta a JSON y se devuelve.

Para usar los datos devueltos, puedes llamar a la función getData() y usar el método .then() para manejar la resolución de la promesa:

getData()
	.then(data => {
	// haz algo con los datos
	});

Alternativa con async/await

En una función asíncrona de nivel superior añades la sentencia try/catch para manejar cualquier error:

async function example() {
	try {
		const data = await getData();
		// haz algo con los datos
	} catch (error) {
		// maneja el error
	}
}

Esta sintaxis facilita la lectura y la comprensión del código asíncrono, y te permite usar los datos devueltos de una forma similar al código síncrono.

Aunque ya existe la opción de utilizar el await sin estar dentro de async en algunos frameworks y versiones de lenguaje, recuerda que esa pareja va junta.

JavaScript en Web Reactiva

Hemos creado contenido premium para ponerte en marcha:

⭐️ Lo que siempre quisiste saber de JavaScript ES6
⭐️ Calculadora de presupuestos con JavaScript 
⭐️ Formulario Atrapahumanos con JavaScript.

Lo mejor de todo, practicar

Una de las mayores ventajas de JavaScript es que puedes ejecutarlo en cuanto quieras en la consola de tu navegador.

Si, aquí mismo, donde estás leyendo esto (sobre todo si estás en el portátil o en desktop).

Abre la consola de desarrollo y copia el código que quieres saber lo que hace y lo ejecutes en consola. Haz cambios, prueba y rompe cosas.

Todos aprendemos así.

¡Manos sobre el teclado!

Escrito por:

Imagen de Daniel Primo

Daniel Primo

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. @delineas en twitter y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.