A few weeks ago I found on my twitter feed a very interesting blog post:
“The Best Frontend JavaScript Interview Questions (written by a Frontend Engineer)”
written by Boris Cherny.
As you may guess, the author shows some interesting questions to ask during a job interview.
Questions are split in 4 parts: Concepts, Coding, Debugging, and System Design. Here, I’ll focus on
the Debugging part.
I really like theses question, because they deal with the specificities of JavaScript: object comparison, event loop, scope, this, prototypal inheritance and the equal operator combined with Abstract Equality Comparison Algorithm.
Before reading the solution, I’d recommend you to find the answer by yourself.
Exercise 1
I want this code to log out “hey amy”, but it logs out “hey arnold” - why?
Answer
Here the problem is the following: { name: 'amy' } != { name: 'amy' }
. When comparing two objects
with equality or strict equality, JavaScript gonna compare the related internal references. Here,
these two objects have the same properties and the same value. But in memory, this is 2 different
objects.
A solution here could be:
Exercise 2
I want this code to log out the numbers 0, 1, 2, 3 in that order, but it doesn’t do what I expect (this is a bug you run into once in a while, and some people love to ask about it in interviews).
Problem
I like this one because it’s a bit trickier and it deals with scope and the JavaScript Event Loop.
The classic pitfall here is the Zero delays. setTimeout(callback, 0)
doesn’t mean that the
callback will be fire after zero milliseconds.
Here’s what happens on the event loop side:
- Current Call Stack is set to the first setTimeout().
- windows.setTimeout() is considered as a Web APIs (for better Non-Blocking I/O). So the call stack sends this part of the code to correct Web APIs. After 0 milliseconds, the callback (here an anonymous function) would be sent to the Queue (not to the call stack).
- As the call stack is free, for-loop can continue to the second setTimeout …(repeat after we meet this condition i < 4)…
- Now the loop is over and
i === 4
. JS can now execute the callback queue one by one. Each console.log(i) will print the 4.
Do you feel lost? I hope this animation will better help you!
Animation made with Loupe (try it it’s fun!)
The second problem is related to scope. The 4 instances of setTimeout function shares the same
instance of i
.
Answer
So, there are several solutions available:
-
use an Immediately-Invoked Function Expression a.k.a. IIFE. The ‘wrapper function’ will run as soon as she’s defined.
-
switch to
let
keyword (instead ofvar
). This (new?) keyword makes scope a bit more easy to understand.
Exercise 3
I want this code to log out “doggo”, but it logs out undefined!
Answer
The previous code return undefined
. Why? Looks, on the first let condition, we define an object
with 2 attributes (name and the function sayName()). Then on the second let, we copy the attribute
sayName, which is a function into another variable. And then, we call this variable out of her
context (in the global one). The function sayName() will return window.name (global if the
environment is Node). And typeof window.name === "undefined"
.
-
👎 (the dirty one). If we want to keep the sayName variable. Then we need to bind the dog the context on it:
This is dirty, right? 🤠
-
👍 call the function directly on her original context
Exercise 4
I want my dog to bark(), but instead, I get an error. Why?
Answer
We got the following error TypeError: fido.bark is not a function. On the previous code, we set
the bark function on another function (Dog()
), which is also a constructor. Is it possible because
in JavaScript, functions are objects.
2 solutions:
-
👎 (the dirty one). fido.bark isn’t a function but
Dog.bark
is. So let’s use this one and solve thethis
issue with a function.prototype.bind() as in the exercise above:But from my point of view using function.prototype.bind() (almost always) lead to confusion.
-
👍 set bark() on the Dog’s prototype
We can also use the class keyword (ES2015) which is just a syntactic sugar to the previous code.
Exercise 5
Why does this code return the results that it does?
Answer
We are using here the simple equality operator (e.g. ==) by opposition to strict comparison (e.g. ===). With this operator, it’s not mandatory to compare the same type.
isBig(1)
pass the conditionthing == 1
as expected.isBig([2])
will pass the conditionthing == 2
. When comparing an array to a number, the array will be converted to a number. This is a part of the Abstract Equality Comparison Algorithm. According to this algorithm, if we compare a number with an Object (reminder: arrays are object in JS), this array will be converted to an array. Here, there is only one item inside so[2] == 2
.
Because this algorithm is obscure for the most common developers, we should avoid this operator (ESLint eqeqeq rule is your friend 👍).
Exercise 6 (bonus)
How to preserve the immutability on my heroes list?
Do you have any idea? 🙂
The answer will be in the next post!
About the author
Hey, I'm Maxence Poutord, a passionate software engineer. In my day-to-day job, I'm working as a senior front-end engineer at Orderfox. When I'm not working, you can find me travelling the world or cooking.
Follow @_maxpou