En las entrevistas de desarrollo front end, es común evaluar el conocimiento profundo de JavaScript, el DOM y CSS. A continuación, se presenta una serie de problemas y conceptos técnicos fundamentales.
Alcance de variables y funciones
Analiza el resultado del siguiente código:
let valorInicial = 50;
actualizarValor(valorInicial);
function actualizarValor() {
valorInicial = 100;
}
console.log(valorInicial); // 100
Si no se utiliza let, var o const dentro de la función, se sobrescribe la variable global.
Tipos de nodos DOM
Para identificar el tipo de un nodo en el DOM, se utiliza la propiedad nodeType. Los valores comunes son: 1 para elementos, 2 para atributos, 3 para texto, 8 para comentarios y 9 para el documento. La propiedad nodeName devuelve el nombre de la etiqueta o del nodo.
Creación de objetos y arreglos
La sintaxis {[]} es inválida para crear un objeto, ya que un arreglo como propiedad requiere una clave. Formas válidas son {}, [{}] y {edad: 25}.
Operadores de incremento y decremento
let contador = 12;
let total = contador++ + ++contador + ++contador * 2 + contador-- + contador--;
console.log(total + ' ' + contador); // 85 13
El orden de evaluación afecta directamente al valor del contador en cada paso de la operación.
Mutación de arreglos
Los métodos shift() y pop() eliminan elementos del inicio y final respectivamente, modificando el arreglo original. splice() permite añadir o quitar elementos en cualquier posición. En cambio, slice() devuelve una copia de un fragmento del arreglo sin alterar el original.
Tipos de datos y palabras reservadas
Los tipos primitivos en JS incluyen string, number, boolean, undefined y null. link no es una palabra reservada, mientras que class, var e instanceof sí lo son.
Números aleatorios y fechas
La expresión parseInt(Math.random() * 3) nunca producirá el número 3, ya que el valor máximo generado antes de truncar es cercano a 2.999. Por otro lado, al crear una fecha como new Date(2023, 12, 8).getMonth(), el resultado es 0, porque los meses se indexan desde 0 (enero) hasta 11 (diciembre); un mes 12 desborda hacia el año siguiente convirtiéndose en enero (0).
Ordenamiento de arreglos
Para ordenar descendentemente un arreglo numérico, se debe proporcionar una función de comparación:
let datos = [25, 111, 18, 12, 92, 5, 15];
datos.sort((x, y) => y - x);
console.log(datos);
Propiedades del documento HTML
El elemento raíz <html> se accede mediante document.documentElement. document.head y document.body devuelven sus respectivos elementos, pero document.html no existe como propiedad estándar.
Métodos de cadenas y arreglos
El método indexOf permite buscar un substring indicando la posición inicial. Por ejemplo, en 'liang zi ju zhen', buscar 'zi' desde el índice 7 retorna -1, ya que no aparece más adelante.
La evaluación de 0.1 + 0.7 == 0.8 es false debido a la imprecisión de la coma flotante en JavaScript.
Distancia de desplazamianto (Scroll)
Para obtener el scroll vertical, se suele usar document.documentElement.scrollTop (en modos estándar) o document.body.scrollTop.
Concatenación de arreglos
let base = [1, 2, 3, 4];
console.log(base.concat(1, 2, 3, [1, 2, 3], 5).length); // 11
El método concat descompone los arreglos pasados como argumentos y añade sus elementos individualmente.
Conversión de tipos y colecciones DOM
parseInt('4aa11')yMath.round(3.5)retornan 4.document.getElementsByClassName()ydocument.querySelectorAll()devuelven listas de nodos (objetos tipo array), mientras quegetElementByIdyquerySelectorretornan un único nodo.
Manipulación de fechas y cadenas
Para sumar 3 días a la fecha actual, se pueden modificar los componentes o usar marcas de tiempo:
let hoy = new Date();
hoy.setDate(hoy.getDate() + 3);
// o alternativamente
hoy.setTime(hoy.getTime() + 3 * 1000 * 60 * 60 * 24);
En las cadenas, length da la longitud, indexOf devuelve un índice, charAt obtiene el carácter, y split (no join) se usa para dividir una cadena en un arreglo.
Métodos DOM y expresiones booleanas
Para remover elementos se usa removeChild, y para insertar appendChild. children es una propiedad, no un método.
La única expresión verdadera entre null instanceof Object, NaN == NaN y false == undefined es null == undefined.
Contexto de ejecución y closures
var nombre = 'mundo';
(function() {
if (typeof nombre === 'undefined') {
var nombre = 'Jack';
console.log('Adiós ' + nombre);
} else {
console.log('Hola ' + nombre);
}
})(); // Imprime "Adiós Jack"
Esto ocurre por el "hoisting": la variable local nombre se eleva al inicio de la función con valor undefined.
Flujo de eventos y descargas
El flujo de eventos tiene fases de captura y burbujeo. addEventListener acepta un tercer parámetro booleano para especificar la fase. Por otro lado, los enlaces a archivos .zip se descargan por defecto en lugar de abrirse en el navegador. En formularios, type="image" actúa como botón de envío enviando coordenadas, y para abrir un enlace en ventana nueva se usa target="_blank" (no existe new).
Preguntas de respuesta abierta
Tipos de datos: Primitivos (string, number, boolean), compuestos (object, function) y especiales (null, undefined).
Coerción de tipos: Evaluar "B" + "a" + + "B" + "a" genera BaNaNa, ya que +"B" resulta en NaN.
Comparación de referencias: [] == [] es false porque se comparan referencias en memoria, no valores.
Asincronía: En un setTimeout con retardo 0, el console.log síncrono se ejecuta antes, imprimiendo el valor original (true).
Mutabilidad:
let arr1 = [1, 2, 3];
let arr2 = arr1;
arr2.push(0);
arr2.concat(6); // No muta arr2
console.log(arr1); // [1, 2, 3, 0]
Funciones y comparaciones:
function verificar() { return 1; }
console.log(verificar === verificar()); // false
console.log(verificar || verificar()); // function verificar()
Almacenamiento web: Las cookies tienen límite de 4KB y se envían al servidor en cada petición. localStorage y sessionStorage permiten guardar 5MB o más. sessionStorage se borra al cerrar la pestaña, mientras que localStorage persiste.
Recortar espacios:
function limpiarEspacios(cadena) {
if (cadena && typeof cadena === 'string') {
return cadena.replace(/^\s+|\s+$/g, '');
}
return cadena;
}
Posicionamiento CSS: relative desplaza al elemento respecto a su posición normal sin sacarlo del flujo. absolute lo extrae del flujo y lo posiciona relativo al ancestro posicionado más cercano.
Comportamiento de this: En llamada directa apunta a window, en métodos al objeto contenedor, y en constructores a la nueva instancia.
Diseño responsivo: Se usa @media screen and (max-width: 600px) para aplicar estilos según la resolución de pantalla.
Pérdida de contexto:
function ejecutar() {
var a = 2;
this.bar();
}
function bar() {
console.log(this.a);
}
A = 6;
bar(); // undefined, ya que window no tiene la propiedad "a"
Atributos data-*: Permiten guardar datos personalizados directamente en el HTML, accesibles mediante la propiedad dataset en JavaScript.
Diferencia entre call, apply y bind: Los dos primeros invocan la función inmediatamente (recibiendo argumentos individuales o un arreglo, respectivamente), mientras que bind crea una nueva función con el contexto fijado.
Flexbox: Es un modelo de diseño unidimensional. Propiedades clave incluyen display: flex, flex-direction, justify-content y align-items.
Implementación de QuickSort
function ordenamientoRapido(arr) {
if (arr.length <= 1) return arr;
let indiceMedio = Math.floor(arr.length / 2);
let pivote = arr.splice(indiceMedio, 1)[0];
let izquierdo = [];
let derecho = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivote) {
izquierdo.push(arr[i]);
} else {
derecho.push(arr[i]);
}
}
return ordenamientoRapido(izquierdo).concat([pivote], ordenamientoRapido(derecho));
}
Manejo del this en eventos
<button id="btn-test">Haz clic</button>
<script>
function MiBoton() {
this.clickeado = false;
this.click = function() {
this.clickeado = true;
console.log(this); // Imprime el elemento DOM
}
}
let instancia = new MiBoton();
document.querySelector('#btn-test').addEventListener('click', instancia.click);
let objetoBoton = {
clickeado: false,
click: () => {
this.clickeado = true;
console.log(this); // Imprime el objeto Window
}
}
document.querySelector('#btn-test').addEventListener('click', objetoBoton.click);
</script>
Las funciones tradicionales cambian su contexto al elemento que dispara el evento, mientras que las funciones flecha (=>) no tienen su propio this y heredan el contexto léxico exterior (en este caso, el global).