3 preguntas de JavaScript a tener en cuenta durante la codificación de entrevistas

JavaScript es el idioma oficial de todos los navegadores web modernos. Como tal, las preguntas de JavaScript surgen en todo tipo de entrevistas con desarrolladores.

Este artículo no trata sobre las bibliotecas de JavaScript más recientes, las prácticas de desarrollo comunes o cualquiera de las nuevas funciones de ES6. Más bien, se trata de 3 cosas que suelen surgir en las entrevistas cuando se habla de JavaScript. A mí mismo me han hecho estas preguntas y mis amigos me han dicho que también se las han hecho.

Por supuesto, estas no son las únicas 3 cosas que debe estudiar antes de una entrevista de JavaScript; hay muchas formas en que puede prepararse mejor para una próxima entrevista, pero a continuación hay 3 preguntas que un entrevistador puede hacer para juzgar qué tan bien sabe y comprende el lenguaje JavaScript y el DOM.

¡Entonces empecemos! Tenga en cuenta que usaremos JavaScript vanilla en los ejemplos a continuación, ya que su entrevistador generalmente querrá ver qué tan bien comprende JavaScript y DOM sin la ayuda de bibliotecas como jQuery.

Pregunta # 1: Delegación de eventos

Al crear una aplicación, a veces deberá adjuntar oyentes de eventos a botones, texto o imágenes en la página para realizar alguna acción cuando el usuario interactúa con el elemento.

Si tomamos una simple lista de tareas pendientes como ejemplo, el entrevistador puede decirle que quiere que ocurra una acción cuando un usuario hace clic en uno de los elementos de la lista. Y quieren que implementes esta funcionalidad en JavaScript asumiendo el siguiente código HTML:


    
  • Walk the dog
  • Pay bills
  • Make dinner
  • Code for one hour

Es posible que desee hacer algo como lo siguiente para adjuntar detectores de eventos a los elementos:

document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); let items = app.getElementsByClassName('item'); // attach event listener to each item for (let item of items) { item.addEventListener('click', function() { alert('you clicked on item: ' + item.innerHTML); }); } });

Si bien esto funciona técnicamente, el problema es que está adjuntando un detector de eventos a cada elemento individualmente. Esto está bien para 4 elementos, pero ¿qué pasa si alguien agrega 10,000 elementos (pueden tener muchas cosas que hacer) a su lista de tareas pendientes? Luego, su función creará 10,000 oyentes de eventos separados y adjuntará cada uno de ellos al DOM. Esto no es muy eficaz.

En una entrevista, sería mejor preguntar primero al entrevistador cuál es el número máximo de elementos que puede ingresar el usuario. Si nunca puede ser más de 10, por ejemplo, entonces el código anterior funcionaría bien. Pero si no hay límite para la cantidad de elementos que el usuario puede ingresar, entonces querrá usar una solución más eficiente.

Si su aplicación pudiera terminar con cientos de detectores de eventos, la solución más eficiente sería adjuntar un detector de eventos a todo el contenedor y luego poder acceder a cada elemento cuando se haga clic en él. Esto se denomina delegación de eventos y es mucho más eficaz que adjuntar controladores de eventos separados.

Aquí está el código para la delegación de eventos:

document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); // attach event listener to whole container app.addEventListener('click', function(e) { if (e.target && e.target.nodeName === 'LI') { let item = e.target; alert('you clicked on item: ' + item.innerHTML); } }); });

Pregunta # 2: Usar un cierre dentro de un bucle

A veces, los cierres se mencionan en una entrevista para que el entrevistador pueda evaluar qué tan familiarizado está usted con el idioma y si sabe cuándo implementar un cierre.

Un cierre es básicamente cuando una función interna tiene acceso a variables fuera de su alcance. Los cierres se pueden usar para cosas como implementar la privacidad y crear fábricas de funciones. Una pregunta de entrevista común sobre el uso de cierres es algo como esto:

Escriba una función que recorra una lista de números enteros e imprima el índice de cada elemento después de un retraso de 3 segundos.

Una implementación común (incorrecta) que he visto para este problema se parece a esto:

const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }

Si ejecuta esto, verá que en realidad obtiene el 4 impreso cada vez en lugar del 0, 1, 2, 3 esperado después de un retraso de 3 segundos.

Para identificar correctamente por qué sucede esto, sería útil comprender por qué sucede esto en JavaScript, que es exactamente lo que el entrevistador está tratando de probar.

La razón de esto es porque la setTimeoutfunción crea una función (el cierre) que tiene acceso a su alcance externo, que es el ciclo que contiene el índice i. Pasados ​​3 segundos, se ejecuta la función e imprime el valor de i, que al final del ciclo está en 4 porque pasa por 0, 1, 2, 3, 4 y el ciclo finalmente se detiene en 4.

En realidad, hay algunas formas de escribir correctamente la función para este problema. Aquí hay dos de ellos:

const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { // pass in the variable i so that each function // has access to the correct index setTimeout(function(i_local) { return function() { console.log('The index of this number is: ' + i_local); } }(i), 3000); }
const arr = [10, 12, 15, 21]; for (let i = 0; i < arr.length; i++) { // using the ES6 let syntax, it creates a new binding // every single time the function is called // read more here: //exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }

Pregunta n. ° 3: rebote

Hay algunos eventos del navegador que pueden activarse muchas veces en un período corto de tiempo muy rápidamente, como cambiar el tamaño de una ventana o desplazarse hacia abajo en una página. Si adjunta un detector de eventos al evento de desplazamiento de la ventana, por ejemplo, y el usuario se desplaza continuamente hacia abajo en la página muy rápidamente, su evento puede dispararse miles de veces en un lapso de 3 segundos. Esto puede causar serios problemas de rendimiento.

Si está discutiendo la creación de una aplicación en una entrevista y surgen eventos como el desplazamiento, el cambio de tamaño de la ventana o la pulsación de teclas, asegúrese de mencionar la eliminación de rebotes y / o la limitación como una forma de mejorar la velocidad y el rendimiento de la página. Un ejemplo real tomado de esta publicación invitada sobre css-tricks:

En 2011, apareció un problema en el sitio web de Twitter: cuando se desplazaba hacia abajo en su feed de Twitter, se volvía lento y no respondía. John Resig publicó una publicación de blog sobre el problema en la que se explicaba lo mala que es la idea de adjuntar funciones costosas directamente al scrollevento.

El rebote es una forma de resolver este problema al limitar el tiempo que debe pasar hasta que se vuelve a llamar a una función. Una aplicación correcta de eliminación de rebotes por lo tanto grupales varias llamadas a funciones en una sola y ejecutar sólo una vez después de que haya transcurrido algún tiempo. Aquí hay una implementación en JavaScript simple que hace uso de temas como alcance, cierres, esto y eventos de tiempo:

// debounce function that will wrap our event function debounce(fn, delay) { // maintain a timer let timer = null; // closure function that has access to timer return function() { // get the scope and parameters of the function // via 'this' and 'arguments' let context = this; let args = arguments; // if event is called, clear the timer and start over clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); } }

Esta función, cuando se envuelve alrededor de un evento, se ejecutará solo después de que haya transcurrido una cierta cantidad de tiempo.

You would use this function like so:

// function to be called when user scrolls function foo() { console.log('You are scrolling!'); } // wrap our function in a debounce to fire once 2 seconds have gone by let elem = document.getElementById('container'); elem.addEventListener('scroll', debounce(foo, 2000));

Throttling is another technique that’s is similar to debouncing, except that instead of waiting for some time to pass by before calling a function, throttling just spreads the function calls across a longer time interval. So if an event occurs 10 times within 100 milliseconds, throttling could spread out each of the function calls to be executed once every 2 seconds instead of all firing within 100 milliseconds.

For more information on debouncing and throttling, the following articles and tutorials may be helpful:

  • Throttling and Debouncing in JavaScript
  • The Difference Between Throttling and Debouncing
  • Examples of Throttling and Debouncing
  • Remy Sharp’s blog post on Throttling function calls

If you enjoyed reading this article, then you may like reading the JavaScript tutorials and solving some of the JavaScript coding challenges that I host on Coderbyte. I’d love to hear what you think!