Analysis of the three most common interview questions in JavaScript

  • 2021-07-26 06:22:22
  • OfStack

Preface

This article is not about the latest JavaScript libraries, day-to-day development practices, or any new ES6 functions. On the contrary, when discussing JavaScript, these three questions often appear in interviews. I have been asked these questions myself, and my friends told me that they have also been asked.

Of course, you shouldn't just study these 3 questions before an JavaScript interview. There are many ways to better prepare for the upcoming interview, but the interviewer may ask the following 3 questions to judge your understanding of JavaScript language and mastery of DOM.

Let's get started! Note that we will use native JavaScript in the following example, because your interviewer usually wants to see how you understand JavaScript and DOM without the help of a third-party library (such as jQuery).

Question # 1: Event delegate

Note: Also called event delegate, time agent, etc.;

When building an application, sometimes you need to bind event listeners to buttons, text, or images on the page to perform certain actions as the user interacts with elements.

If we take a simple to-do list as an example, the interviewer may tell you that they want to do something when the user clicks on one of the list items.

They want you to do this with JavaScript, assuming the code for HTML is as follows:


<ul id="todo-app">
 <li class="item">Walk the dog</li>
 <li class="item">Pay bills</li>
 <li class="item">Make dinner</li>
 <li class="item">Code for one hour</li>
</ul>

You might imagine binding an event listener in an element like this:


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

Although this implements functionality, the problem is that you bind event listeners to each list item individually. This is four elements, not a big problem, but what if someone adds 10,000 items to their to-do list (they may have a lot of things to do)? Your function will then create 10,000 separate event listeners and bind each event listener to DOM. This code execution is very inefficient.

In an interview, it is best to first ask the interviewer what is the maximum number of items that users can enter. If it never exceeds 10, the above code will work properly. However, if there is no limit to the number of items users can enter, then you should use a more efficient solution.

If your application may end up with hundreds of event listeners, a more efficient solution is to actually bind one event listener to the entire container, and then access each exact element when actually clicked. This is called an event delegate, and it is more efficient to bind an event handler separately for each element.

Code delegated with events:


document.addEventListener('DOMContentLoaded', function() {
 
 let app = document.getElementById('todo-app');
 
 //  Event listeners are bound to the entire container 
 app.addEventListener('click', function(e) {
 if (e.target && e.target.nodeName === 'LI') {
 let item = e.target;
 alert('you clicked on item: ' + item.innerHTML);
 }
 });
 
});

Problem # 2: Using closures within loops (Closures)

Closures often appear in interviews so that the interviewer can measure your familiarity with the language and whether you know when to use closures.

The essence of a closure is that an internal function accesses a variable outside its scope. Closures can be used to implement things like private variables and create factory functions. A common interview question about using closures is this:

Write a function that loops through the list of integers and prints the index of each element after a delay of 3 seconds.

The most common (but incorrect) problem I see is an implementation like the following:


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);
}

If you run the above code, after a delay of 3 seconds, you will see that each printout is actually 4 instead of the expected 0, 1, 2, 3.

It is useful in JavaScript to understand exactly why this is happening, which is what the interviewer really intends to do.

The reason for this is that the setTimeout function creates a function that can access its external scope (which is often referred to as a closure), and each loop contains the index i.
After 3 seconds, the function is executed and prints out the value of i, which is 4 at the end of the loop because its cycle goes through 0, 1, 2, 3, 4, and the loop finally stops at 4.

In fact, there are several correct ways to solve this problem, and two are listed below:


const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
 //  By passing variables  i
 //  You can get the correct index in each function 
 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++) {
 //  Use ES6 Adj. let Syntax, which creates a 1 New bindings 
 //  Each method is called individually 
 //  For more details, please read : http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads
 setTimeout(function() {
 console.log('The index of this number is: ' + i);
 }, 3000);
}

Question # 3: Function anti-jitter (Debouncing)

There are 1 browser events that can be quickly launched multiple times in a very short time, such as resizing a window or scrolling down a page. For example, if you bind an event listener to a window scroll event and the user continues to scroll down the page very quickly, your event may be triggered thousands of times in a range of 3 seconds. This may cause some serious performance problems.

If you discuss building applications and events in an interview, such as scrolling, window resizing, or keyboard pressing events, be sure to mention function stabilizer (Debouncing) and/or function throttling (Throttling) to improve page speed and performance. 1 real case from guest post on css-tricks:

In 2011, a problem was raised on Twitter: When you scroll through Twitter feed, it becomes very slow or even unresponsive. John Resig published a blog post on this issue, explaining how bad it is to bind functions directly to scroll events.

Function anti-jitter (Debouncing) is a way to solve this problem by limiting the time that needs to elapse until the function is called again. A correct way to realize function anti-shake is to call multiple functions in one function and execute them once every 1 fixed time. Here is an example implemented using native JavaScript, using scopes, closures, this, and timed events:


// debounce Function is used to wrap our events 
function debounce(fn, delay) {
 //  Persistence 1 Timer  timer
 let timer = null;
 //  Closure functions can access  timer
 return function() {
 //  Pass  'this'  And  'arguments'
 //  Get the scope and parameters of the function 
 let context = this;
 let args = arguments;
 //  If the event is triggered, clear  timer  And restart the timing 
 clearTimeout(timer);
 timer = setTimeout(function() {
 fn.apply(context, args);
 }, delay);
 }
}

When this function is bound to an event, it will not be called until a specified period of time has elapsed.

You can use this function like this:


//  The function is called when the user scrolls 
function foo() {
 console.log('You are scrolling!');
}
 
//  Two seconds after the event triggered, we wrapped it in debounce The function in will be triggered 
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));

Function throttling is another skill similar to function anti-shake. In addition to waiting for a period of time before calling a function, function throttling also limits it to be called only once in a fixed time. Therefore, if an event occurs 10 times in 100 milliseconds, function throttling will call the function once every 2 seconds instead of calling it all in 100 milliseconds.

Summarize


Related articles: