The Ultimate Guide to Job Interview Questions
Javascript Interview Questions
Introduction
Full-stack and front-end developer positions are two of the most popular types of programming roles right now. This means there is increasing pressure on recruiters and hiring managers to find people with the right skillset for these positions. The following are some common questions about the Javascript programming language the answers to which most candidates for these roles should know.
The questions are broken down into three categories. The first category are questions that can be asked during a phone screen as they require only verbal answers. Any full-stack or front-end developer should be able to answer them without much difficulty.
The second group of questions are similar to the first in that their answers can be verbal but they are a bit more difficult to answer than the first and require a deeper understanding of the language. They can be asked during a phone screen if the candidate has answered questions from the first group to your satisfaction.
Finally, the third category are questions that are best suited to an in-person interview where the candidate can write out the answers either on a whiteboard or a computer. They are designed to show that not only does a candidate has knowledge of language fundamentals but that they have the chops to go with it.
Don’t forget that one of the best ways to evaluate the candidate’s skills for your project is to perform a hands-on programming assessment.
Check out the JavaScript question below. There are multiple ways to solve it, so the candidate’s choices can reveal how they code. How would you solve it? Click on the “Instructions” tab and try it out:
Preliminary Screening Questions
What is the difference between undefined and null in JavaScript?
At first blush these two things seem to be similar but are actually quite different. First of all, they have different types:
> typeof(undefined)
"undefined"
> typeof(null)
"object"
null is a value that can be assigned to a variable and means “no value”. However, variables that have been declared but not yet assigned a value are “undefined”. This is true not only of variables but also array keys and object members that do not exist, function parameters that have not been given and the result of calling a function that does not return a value.
To sum up, null is the value that means “no value” and undefined is the type of variables that have not been given a value.
What is the difference between == and ===?
The answer to this question is rather simple but an incorrect answer by a candidate should be considered a red flag. The answer is that == performs any necessary type conversions before doing the comparison whereas === does not. The Javascript equality table is rather infamous and it’s considered a good practice to always use === when comparing values for equality.
What does the use strict; directive do?
The purpose of the use strict; directive is to ensure that code is executed in strict mode. So what is “strict mode”? Strict mode helps developers avoid a handful of pitfalls in Javascript. Enabling strict mode means that the following will result in an error.
- Not declaring a variable. This helps avoid mistyping a variable name as the mistyped variable will appear to be a new, undeclared variable.
- Deleting a variable, i.e., delete x;
- Writing to a read-only property (read-only properties are those defined via Object.defineProperty()).
- Using variables with names like arguments or eval.
- Use of the with statement.
An answer to this question should include one or more of the above. Bonus points can be given if the candidate says something about the scope of strict mode. In particular, if use strict; is at the top level, then it applies to the entire module but if it is found inside a function definition, it applies only to the code in the body of the function.
Explain what a callback function is and provide a simple example.
A callback is a function passed as an argument into another function and is called when the function (the one the callback is passed into) completes.
The following shows a generic use of callbacks.
function doIt(onSuccess, onFailure) {
var err = ...
if (err) {
onFailure(err)
} else {
onSuccess()
}
}
Any mention of the use of the use of Promise’s (see below) instead of callbacks should be considered a good sign.
What’s a pure function and why should you care?
A pure function is a function that returns a value that depends only on its input arguments and additionally has no side effects. These are functions in the mathematical sense. Pure functions are the cornerstone of functional programming which has become increasingly popular over the years. Programming with pure functions is desirable because they are easier to reason about since there is no context that needs to be considered when using or debugging them. It also make refactoring simpler since pure functions can be moved (or removed) without affecting the behavior of the program. They give rise to what’s known as “referential transparency” and bonus points can be awarded if a candidate mentions this.
Deep-dive Questions
What is a closure?
Wikipedia says:
…a closure is a record storing a function together with an environment.
A closure can be tricky to define on the spot but any mention of “function” together with “environment” or “scope” can be considered to be on the right track. A closure gives a function access to variables that would be unavailable to it without the closure.
It has become common to wrap the contents of a Javascript file in a function. Why is this done?
This technique has been used to create a kind of namespace for a module so that variables defined in the module are private and therefore will not clash with variables in the global namespace or in other modules.
Here is an example:
var queue = (function () {
var items = [];
return {
enqueue: function (item) {
items.push(item);
},
dequeue: function () {
if (items.length > 0) {
var next = items[0];
items.shift();
return next;
} else {
throw "Cannot dequeue from an empty queue";
}
}
};
})();
In the above implementation of a queue data structure (another good in-person interview question) the variable items is private to the implementation and is not viewable or modifiable by clients of a queue.
This technique is known as “Immediately Invoked Function Expression” or IIFE. You can read more about it on the Mozilla Developer Network and on Wikipedia.
This technique can be generally useful for data hiding and namespacing but modern Javascript bundlers like webpack have become popular for achieving the same effect.
What are Promises used for?
Promises are used for asynchronous programming. They allow Javascript programs to be written in a non-blocking fashion just as using normal callbacks do, but without the mental overhead of that technique. People often refer to the callback hell that often occurs when using callbacks to achieve asynchrony. Promises were created to alleviate this problem.
Give an example of combining multiple Promises.
There are several ways that multiple Promises can be combined. The most important one (and the one that any candidate should absolutely be aware of) is the then() method of a Promise. This is the way that Promises are sequenced; that is, when functions that return Promises must be called on values contained in previously run Promises.
Another method is Promise.all() which is used to create a single Promise from multiple independent Promises. In this case the new Promise is resolved when all of the given Promises have been resolved.
Finally, there’s Promise.race() which is similar to Promise.all() in that it creates one Promise from several others but differs in that the new Promise is resolved when only one of the given Promises resolve, in particular, the one that resolves first.
What are the async / await keywords used for?
Promises have been successful at alleviating the problems associated with a strictly callback solution to asynchronous programming but they can be difficult to use when lots of Promises are involved and must be sequenced with then() as well as having to handle errors associated with all that chaining.
The async / await keywords are used to allow developers to write code that feels very much like old-fashioned imperative code -or sequential code- but that is still asynchronous.
Candidates should know when it is appropriate and possible to use these keywords. In particular they should know that async can only be placed before the function keyword on a function definition. This marks the function as returning a Promise. The await keyword can only be used inside such an asynchronous function and must be placed before a call to a function that will return a Promise.
Whiteboard Questions
Write code to convert an array of strings to an array of the lengths of those strings.
This should be a relatively easy exercise for someone familiar with Javascript to complete. An ideal solution to this problem should look something like this:
var words = ["the", "quick", "brown", "fox"];
var wordLengths = words.map(word => word.length);
// wordLengths = [3, 5, 5, 3]
Another version might use forEach:
var wordLengths2 = [];
words.forEach(word => wordLengths2.push(word.length));
Finally, using an old-fashioned for loop will do the trick:
var wordLengths3 = []; var i; for (i = 0; i ❰ words.length; i++) { var word = words[i]; wordLengths3.push(word.length); }
The last two should be considered a bit of a red flag as it shows that the candidate is not very familiar with the most common of higher-order functions: map.
Write code to sum an array of numbers.
A good candidate should be able to come up with something like the following solution:
const nums = [1, 2, 3, 4, 5];
const summer = (a, b) => a + b;
const sum = nums.reduce(summer, 0);
As with the previous question this problem can also be solved using a for or a forEach but those solutions should similarly be considered inferior and a red flag.
This question allows for some good follow-up questions.
What is the summer function for and what are the values passed to it?
The candidate should be able to explain that the summer function (known also as a reducer function) is called for each element of the array and that the first value passed to it is an accumulator and the second argument is the current element of the array. The accumulator is result of the call to the reducing function for the previous element of the array. Some leniency can be given to candidates that may get the order of these two arguments reversed since different languages are known to use the reverse ordering and that’s the sort of information that is easily found with a Google search.
If the candidate gives an answer similar to the above, then another good follow-up question is:
If the accumulator holds the result of the reducing function for the previous array element, what is its value for the first array element?
A competent candidate will know that this is precisely what the second argument to reduce is for: the initial value of the accumulator used when reducing the first element of the array. If the candidate hasn’t already given an answer to this next question, ask it.
The second argument to reduce is optional. What happens if you don’t supply it?
In that case the first element of the array is used as the initial value and the reduction continues with the second element of the array. This answer sets you up for this final follow-up question:
What happens in the case that reduce is called on an empty array without providing the optional initial accumulator value?
This situation causes an error. The candidate might expand on this and say that an initial value should always be supplied or otherwise code should ensure that the array is not empty.
Write a function that can be called like so: greeter(“Hello”)(“Candidate”) and will log “Hello, Candidate!” to the console
Sharp candidates will recognize this technique as currying where functions are able to accept fewer than the total number of arguments. Calling such a function is known as partial application. Any mention of these is a good sign. They may also comment that this is a higher order function (HOF) since it is implemented as a function returning another function.
An implementation might look like this:
function greeter(greeting) {
return function (greetee) {
console.log(greeting + ", " + greetee + "!");
}
}
In a language like Javascript currying is achieved by returning functions from functions. Here, the outer function (greeter) supplies the greeting to be used while the returned function allows the caller to supply the name of the greetee.
What is the output of the following code?
(function(){
var a = b = 42;
})();
console.log(typeof a);
console.log(typeof b);
This problem is designed to probe a candidate’s knowledge of Javascript’s variable hoisting rules. Developers unaware of these rules may assume that “undefined” will be logged to the console twice, once each for both a and b, or if they’re not paying attention, may think that “42” is logged to the console twice, but neither of these is what happens.
The above code will output to the console
> undefined
> 42
Why? The variable a is undefined because it is scoped to the anonymous function and goes out of scope when the function completes. b on the other hand is in the global scope. This is because it is not declared inside the function; the var keyword only applies to a here, so b is hoisted to the global scope.
This is another good reason to enable strict mode; the above code would be an error in that case. Even when using strict mode the let or const keywords should be preferred to var in most cases.
Conclusion
The ability of your company to remain competitive and bring your products to market before the competition depends on a lot of factors but one of the most important is the quality of the developers you have creating those products. These Javascript interview questions will help you in the task of finding the best developers in your pool of candidates but ultimately it’s up to you to decide to what standard they will be held.
Use as many or as few of these interview questions as you see fit; you need not use them all on one candidate. These questions represent what we feel will give you the ability to probe a candidate’s general as well as deep knowledge of Javascript and its frameworks (as React, Angular 2, and, Ember.js). But you should not feel limited to only these questions. Feel free to come up with your own and if you find some that you think are helpful, please let us know; we’d love to hear them!