DEV Community

Alejandro Oviedo
Alejandro Oviedo

Posted on

JavaScript Interview Questions

After a few interviews this month I wanted to share a few nice exercises that would come up in technical interviews, and how I originally approached them.

Asynchronous for-loop

This exercise is related to how asynchronous programming work. If you asked me, I would rather ask about how the event loop works instead of asking this particular question.

You are given the following code:

for(var i = 0; i < 10; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000);
}
Enter fullscreen mode Exit fullscreen mode

and you're asked two questions

  1. what's the output?
  2. what would you add to print the numbers from 0 to 9

I will leave the first answer as an exercise for the reader but question n°2 should already give you a hint.
To answer the second question what you want is to store for every iteration the value of the variable i so that they can be accessed later on by the setTimeout. One of the many alternatives is to create an IIFE (maybe better called IIAF in this case?):

for(var i = 0; i < 10; i++){
    (n => {
        setTimeout(() => {
            console.log(n);
        }, 1000);
    })(i);
}
Enter fullscreen mode Exit fullscreen mode

Bonus

Would you be able to explain in the comments why this little change works as expected?

for(let i = 0; i < 10; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000);
}
Enter fullscreen mode Exit fullscreen mode

Reduce

The goal of this exercise is to define a function that does exactly the same than Array.prototype.reduce but receiving the array as first parameter (much like lodash's counterpart).

Iterative

This is the most intuitive solution for me, using an accumulator to carry on the result of each function execution.

function reduce(arr, fn, def) {
    let accum = def;
    for(let i = 0; i < arr.length; i++) {
        accum = fn(accum, arr[i]);
    }
    return accum;
}
Enter fullscreen mode Exit fullscreen mode

Recursive

The recursive version has the requirement of knowing about an specific array operation: removing the first element of an array and get an array with the remaining elements. Of course I didn't knew which function did exactly that from the top of my head and the interviewer was kind enough to mention Array.prototype.slice. It is also important to clarify that Array.prototype.slice doesn't modifies the array itself but returns a copy of it.

function reduce(arr, fn, def) {
    // base case: there are no more elements in the array and the function should finish
    if(arr.length === 0) {
        return def;
    }
    return reduce(arr.slice(1), fn, fn(def, arr[0]));
}
Enter fullscreen mode Exit fullscreen mode

Minimalistic

There's a growing interest for tweet-sized solutions, minimizing the characters used for a solution and thought it would be a nice exercise to add it here. I wouldn't recommend to include this type of solutions in your codebase though.

function reduce(arr, fn, def) {
    return arr.length === 0 ? def : reduce(arr.slice(1), fn, fn(def, arr[0]));
}
Enter fullscreen mode Exit fullscreen mode

Map

For this exercise you're asked to write a map function that would replicate the behavior of Array.prototype.map.

Iterative

function map(arr, fn) {
    const result = [];
    for(const elem of arr) {
        result.push(fn(elem));
    }
    return result;
}
Enter fullscreen mode Exit fullscreen mode

Using reduce

This is when things started to get interesting. I was told to only use the reduce function previously implemented to write the map function and my first thought was doing something like:

function map(arr, fn) {
    const result = [];
    reduce(arr, (curr, next) => {
        result.push(fn(next));
        return curr;
    });
    return result;
}
Enter fullscreen mode Exit fullscreen mode

which is not incorrect, but was later asked "what if we don't want to use a intermediate variable?" which got me thinking...

function map(arr, fn) {
    return reduce(arr, (curr, next) => {
        curr.push(fn(next));
        return curr;
    }, []);
}
Enter fullscreen mode Exit fullscreen mode

Minimalistic

function map(arr, fn) {
    return reduce(arr, (curr, next) => curr.push(fn(next)) && curr, []);
}
Enter fullscreen mode Exit fullscreen mode

I've prepared a few playgrounds in CodeSandbox for you to try and solve them if you like:

  1. Reduce
  2. Map

There are many sites that you can use to practice with similar (or more complex) exercises like Hackerrank or Codility.

Are there any other interesting exercises that you were asked to do? Let me know in the comments!

Top comments (1)

Collapse
 
danmantey profile image
Mantey Daniel

@a0viedo can u explain further why the IIFE and the let worked