
Hi Habr! There is one question, in appearance - not so difficult, which is often asked to developers at interviews.
Today we will analyze it and talk about the approaches to finding an answer. Asking the question in question, the interviewer suggests telling you about what the following code will produce:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { setTimeout(function() { console.log('Index: ' + i + ', element: ' + arr[i]); }, 3000); }
Do you know what will appear in the console?
Just want to say that this question is aimed at understanding such JS mechanisms as
closures ,
scopes, and the
setTimeout function. The correct answer is:
')
Index: 4, element: undefined Index: 4, element: undefined Index: 4, element: undefined Index: 4, element: undefined
If you were expecting something else, we hope, in this material we will be able to tell about why the output of this code fragment turned out to be exactly like this, and how to bring it into a more decent look.
Why is this question so popular?
One Reddit user
talked about being asked such a question during an interview at Amazon. I myself faced similar questions aimed at understanding the cycles and closures in JS, even at an interview at Google.
This question allows you to check the ownership of some important JavaScript concepts. Considering the peculiarities of the JS operation, the situation that is modeled in the presented code fragment can often arise in the course of the actual work. In particular, this concerns the use of
setTimeout
or some other asynchronous function in a loop.
A good understanding of the functional and block scopes in JavaScript, the features of the device anonymous functions, closures and
IIFE , will help your professional growth and allow you to show yourself from the good side during interviews.
Approaches to answering a question and getting rid of undefined
In fact, I already wrote about possible approaches to answering this question in some of my previous materials. In particular, in
this and
this . Let me quote some of these publications:
The reason for this is that the function
setTimeout
creates a function (closure), which has access to the external visibility area, represented in this case by a loop, in which the variable
i
declared and used. After 3 seconds have passed, the function is executed and displays the value of
i
, which, after the end of the cycle operation, remains available and equals 4th. The variable, during the cycle operation, successively takes the values โโ0, 1, 2, 3, 4, moreover, the last value is stored in it after it exits the cycle. There are four elements in the array, with indices from 0 to 3, therefore, trying to refer to
arr[4]
, we get
undefined
. How to get rid of
undefined
and make the code output what is expected of it, that is, the values โโof the elements of the array?
Here are a couple of common approaches to solving such a problem, and specifically to ensuring access to the desired value of the loop variable within the function called
setTimeout
.
The first involves the transfer of the required parameter to the internal function, the second is based on using the capabilities of ES6.
So, here is the first option:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { // i, // setTimeout(function(i_local) { return function() { console.log('The index of this number is: ' + i_local); } }(i), 3000); }
Here is the second option:
const arr = [10, 12, 15, 21]; for (let i = 0; i < arr.length; i++) { // let, ES6, // // : http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }
On Reddit I managed to find a
similar answer to this question. Here is a good
explanation of the features of closures on StackOverflow.
Results
It may be noted that the question with which we started this material often confuses people with little experience in JavaScript or in functional programming. The reason is a misunderstanding of the essence of closures. When forming a closure, it does not transfer the value of the variable or a reference to it. The closure captures the variable itself.
Dear readers! Do you know any interesting questions that are asked during JavaScript interviews? If yes, please share.