It takes 6 minutes to read and 2 minutes to speed read. This article was first published on Zhihu weekly. I’ve interviewed hundreds of front-end engineers over the past two years as an interviewer and was surprised to find that more than 80% of the candidates failed to get a passing grade on this question. What kind of magical interview question is this? What abilities does he look for in candidates? What does that mean for you as you read this? Just listen to me slowly
Humble beginnings
Recruitment of front-end engineers, especially senior front-end engineers, a solid JS foundation is absolutely necessary, the foundation is not solid engineers in the face of various problems in the front-end development of large probability will be at a loss. When looking at a candidate’s JS base, I often provide the following code and ask the candidate to analyze the result in action:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
console.log(new Date, i);Copy the code
This is a very short code, it’s only seven lines, and I don’t think anyone who can read this needs me to explain what this code is doing line by line. Candidates give different results when presented with this code, and here’s a typical answer:
- A. 20% of people scan the code quickly and give the result:
0,1,2,3,4,5
; - B. 30% of people take the code line by line and give the result:
5,0,1,2,3,4
; - C. 50% of the people take the code and chew it over and come up with the result:
5,5,5,5,5,5
;
The correct answer is C, as long as you understand the difference between synchronous and asynchronous code in JS, variable scope, closure, etc.
2017-03-18T00:43:45.873z 5 2017-03-18T00:43:46.866z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 2017-03-18T00:43:46.868z 5 The 2017-03-18 T00:43:46. 868 z 2017-03-18 T00:43:46. 868 zCopy the code
Next, I ask: What if we agreed that an arrow indicated that the interval between the two outputs was 1 second, and a comma indicated that the interval between the two outputs was negligible? There are two answers:
- A. 60% would describe it as:
5 -> 5 -> 5 -> 5 -> 5
, that is, there is a 1 second interval between each 5; - B. 40% would describe it as:
5 - > 5,5,5,5,5
, that is, the first 5 is printed directly. After 1 second, 5 5 are printed.
This requires the candidate to be very familiar with the working mechanism of timers in JS. During the cycle execution, 5 timers are almost set at the same time. Under normal circumstances, these timers will be triggered after 1 second, and the output of the cycle is executed immediately.
If this is a passing grade, 20 out of 100 people will pass the interview, so those of you reading this can think about it, did you pass?
Question 1: Closures
5 -> 0,1,2,3,4, 5 -> 0,1,2,3,4 Those familiar with closures will quickly come up with the following solutions:
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(new Date, j);
}, 1000);
})(i);
}
console.log(new Date, i);Copy the code
Elegant use of IIFE (Immediately Invoked Function Expression: It’s a good idea to solve the problem caused by closures, but the code may not be easy for beginners to understand, at least when I first started thinking about it.
Is there something more intuitive to do? The answer is yes, we just need to tweak the body of the loop so that the output code gets the I value for each loop. How do you do that? By taking advantage of the Primitive Type in JS that is passed by Value, it is not difficult to modify the following code:
var output = function (i) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
};
for (var i = 0; i < 5; i++) {
output(i); // The I value passed here is copied
}
console.log(new Date, i);Copy the code
Candidates who can provide the above two solutions are considered to have a good understanding of the basics of JS and will receive 10 points for each. Of course, some candidates give the following code in the actual interview:
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
console.log(new Date, i);Copy the code
Careful students will notice that there is only one very subtle change: var is replaced by let in ES6 Block Scope, but the code will actually run with an error because the last output uses an I that does not exist in its Scope; I only exists inside the loop.
Students who can think of ES6 features did not answer correctly, but showed their understanding of ES6, can add 5 points, continue to follow the question.
Follow-up 2: ES6
Experienced front end students read here may be a little impatient, pulled so much, is he knows the content, don’t worry, the challenge will continue to increase.
If you want the output to be 0 -> 1 -> 2 -> 3 -> 4 -> 5, and you want the loop and two console. logs in the original code block to remain unchanged, how do you change the code? The new requirements can be accurately described as: When the code is executed, output 0 immediately, and then output 1,2,3,4 every second. At the end of the cycle, output 5 at about the fifth second (use about here, is to avoid the students stuck in the trap, because the timer trigger time in JS may be uncertain, For details, see How Javascript Timers Work).
Seeing this, some of you will give the following possible solution:
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(new Date, j);
}, 1000 * j); // Change the timer time from 0 to 4
})(i);
}
setTimeout(function() { // Set the timer to 5 seconds
console.log(new Date, i);
}, 1000 * i);Copy the code
Admittedly, this is crude and effective, but it’s not exactly a bonus. How would the code be organized if you abstracted the requirement to do something else after a series of asynchronous operations (one asynchronous operation per loop) were completed? Are you wise enough to remember something? Yeah, Promise.
Some students might ask, isn’t it just output a few numbers on the console? As for killing chickens like this? You know, what the interviewer is really looking for is the ability and quality of the candidate, because in modern front-end development, asynchronous code is ubiquitous, and familiarity with the flow control of asynchronous operations is essential to becoming a qualified developer.
Along the way, it’s not hard to come up with a promise-based solution (since Promises are a new feature in ES6, wouldn’t our new code be better written in ES6? Your interviewer will most likely like you if you do:
const tasks = [];
for (var i = 0; i < 5; i++) { // The declaration of I cannot be changed to let. What should I do if I want to change?
((j) = > {
tasks.push(new Promise((resolve) = > {
setTimeout((a)= > {
console.log(new Date, j);
resolve(); // Resolve must be used, otherwise the code will not work as expected
}, 1000 * j); // The timeout period of the timer gradually increases
}));
})(i);
}
Promise.all(tasks).then((a)= > {
setTimeout((a)= > {
console.log(new Date, i);
}, 1000); // Note that you only need to set the timeout to 1 second
});Copy the code
In comparison, I prefer the following code which looks more concise. You should know that the programming style is also the point that many interviewers focus on. The smaller granularity and better modularity of code reading will undoubtedly be a plus point.
const tasks = []; // Where to store promises for asynchronous operations
const output = (i) = > new Promise((resolve) = > {
setTimeout((a)= > {
console.log(new Date, i);
resolve();
}, 1000 * i);
});
// Generate all asynchronous operations
for (var i = 0; i < 5; i++) {
tasks.push(output(i));
}
// After the asynchronous operation is complete, print the last I
Promise.all(tasks).then((a)= > {
setTimeout((a)= > {
console.log(new Date, i);
}, 1000);
});Copy the code
For those of you reading this, congratulations, your next interview with a similar question will get at least 80 points.
We all know that using promises to deal with asynchronous code makes it more readable than the callback mechanism, but the problem with using Promises is that if you don’t deal with Promise reject, errors are thrown into a black hole. The good news is that newer Versions of Chrome and Node 7.x have an Unhandled Rejection Warning for exceptions that have not been handled, and it takes some special tricks (browser, Node.js) to handle them.
Follow-up 3: ES7
Now that you’ve seen this, hold on for another two minutes, and the rest of this will show you that it was worth it.
Most interviewers before decide to hire a candidate also need to inspect another important ability, namely technology since the drive, bluntly said is internal candidate as a motor to drive him, with a beautiful way to solve the problem of engineering field, with business and technology becomes more and more cow force, what is cool? I suggest reading this profile of Programlife.
Back to the point, now that the Promise has been taken down, how can I use the async await feature in ES7 to make this code more concise? Can you give an answer based on what you know so far? Pause here for a minute and think about it.
The following is the reference code given by the author:
// Emulates sleep in other languages, which can be virtually any asynchronous operation
const sleep = (timeountMS) = > new Promise((resolve) = > {
setTimeout(resolve, timeountMS);
});
(async () = > { // Declare the async function expression to execute
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(new Date, i);
}
await sleep(1000);
console.log(new Date, i); }) ();Copy the code
conclusion
Thank you for taking the time to read this, I believe that you will not only gain a variety of skills to accurately control the code output with JS, but also for the growth expectations of front-end engineers: a solid language foundation, the ability to keep pace with The Times, strong technical drive.
One More Thing
This article first zhihu column, commercial reprint please contact the author to obtain authorization, non-commercial reprint please indicate the source. If you found this article helpful, please give it a thumbs up! If you have any questions about the content of this article, please leave a comment. Want to know what I’ll write next? Welcome to subscribe zhihu column: “Front End Weekly: Keep you up to date in the front End field”.