Table of Contents

1. Emulate Vue.js

This challenge came up during a phone interview. I was asked to head over to the Vue.js docs, and copy the following snippets to my editor of choice:

The goal was, as you can imagine, to make it so {{ message }} gets replaced by Hello Vue! without, of course, adding Vue.js as a dependency.

Before you jump into the code, always clarify with the interviewer any questions you might have about the problem, and make sure you completely understand what is the input, the output, and any edge case you need to account for.

To get started, let’s create our Vue class, and add it above the Javascript snippet.

class Vue {

constructor(options) {

}

}

With that, our little project should at least run without errors.

Now, in order to replace the template string with the provided text, probably the easiest way is to, once we have access to the #app element, use String.replace() on its innerHTML property:

This gets the job done, but we can definitely do better. For example, this implementation does not work as expected if we have two template strings with the same name. Only the first occurrence will be replaced.

<div id="app">

{{ message }} and {{ message }}, what's the {{ message }}

</div>

That’s easy to fix — we use a RegExp with the global flag new RegExp(`{{ ${key} }}`, “g”) instead of `{{ ${key} }}` .

Also, innerHTML is expensive, as the value is parsed as HTML. We should use textContent or innerText . To learn more about the difference between the three, click here.

Simply replacing innerHTML with either innerText or textContent works for our simple markup, but it quickly falls short as soon as our markup becomes more complex:

<div id="app">

{{ message }}

<p> another {{ message }} inside a paragraph </p>

</div>

You will notice that the <p> tags will be removed from the DOM. That’s because innerText and textContent return only text, and when it’s used as a setter it replaces the markup with just text.

One way to deal with this is to traverse the DOM, find all the text nodes, and then replace the text.

There’s still one more thing that we should improve. Whenever we find a text node, we look for template strings n times (n, in this case, is the number of data entries). So, if we have 200 entries, even if our DOM node looks like this:

<p>Nothing to see here</p>

We will still iterate 200 times trying to find template strings.

One way to fix this is to implement a simple state machine that looks at the text once and replace template strings (if any) as it goes:

This is far from being production-ready, but it’s something you should be able to come up with in about 30–45 minutes.

Be sure to talk about how you could improve it even further, performance problems (good segway to show off your Virtual DOM knowledge), and bonus points if you can talk about how you would implement loops and conditionals and handle user input.

You can see the code above running in the sandbox below:

2. async series and parallel

Before RxJs, Promises and async/await were industry standards, writing asynchronous Javascript wasn’t easy, and you would often be a victim of the Callback Hell (aka The Pyramid of Doom). And because of that, libraries like async were created at the time.

The following two-part challenge happened during an on-site interview. I had been asked to bring my own laptop, so I knew there was going to be a live coding session.

async.series

Run the functions in the tasks collection in series, each one running once the previous function has completed. If any functions in the series pass an error to its callback, no more functions are run and callback is immediately called with the value of the error. Otherwise, callback receives an array of results when tasks have completed.

Let’s start by creating our async object:

const async = {

series: (tasks, callback) => {}

};

The main thing about this challenge is that we need to ensure we execute one function after the other. In other words, we only execute a function after the previous one is done:

We use a variable i to keep track of the current function being executed, and we create an internal callback to check for errors, increment i and execute the next function.

For the sake of simplicity, we are not validating the input or using try/catch for better error handling, but you should always discuss that with your interviewer.

async.parallel

Run the tasks collection of functions in parallel, without waiting until the previous function has completed. If any of the functions pass an error to its callback, the main callback is immediately called with the value of the error. Once the tasks have completed, the results are passed to the final callback as an array.

Let’s start by adding a new parallel function to our async object:

const async = {

series: (tasks, callback) => {}

parallel: (tasks, callback) => {}

};

The parallel differs from the series one, in the sense that we can fire all the functions at the same time. We just need to be careful when collecting the results, so they are put in the correct position of the array.

We start with a done flag that prevents the callback from being called after an error, and a count that keeps track of how many functions have completed so we know when to stop. We have an internal callback that is responsible for collecting the results and calling the user’s callback. And finally, we trigger all the functions at once.

The final code is available here:

3. A draggable button that changes the background color

During an on-site interview, I was asked to implement a button in the middle of the screen that can be dragged around. As it moves towards the edges, the background color changes from white to red.

Before we talk about a possible solution, see the result and code here.

Let’s start by creating our markup:

<html>

<body>

<div id="overlay"></div>

<div id="button" draggable="true"></div>

</body>

<html>

The #overlay will be covering the whole screen, and it’s the element we will use to change the background color. The #button is our draggable button.

This is the CSS, to style the button and overlay:

#button {

cursor: pointer;

background-color: black;

width: 50px;

height: 50px;

border-radius: 50px; position: absolute;

top: 50%;

left: 50%;

transform: translateX(-50%) translateY(-50%);

} #overlay {

background-color: red;

width: 100vw;

height: 100vh;

z-index: -1;

opacity: 0;

}

The way we will change the color is through the overlay opacity. It is 0 (transparent) by default, and we will use javascript to change it accordingly.

During this challenge, I was allowed to use any libraries I wanted. I knew the company used Typescript and RxJS, so I decided to use them. There are two main things we need to do — subscribe and handle the drag events, and determine the overlay opacity based on the event X and Y coordinates.

We will tackle the former by using fromEvent and subscribe . This can totally be done with vanilla Javascript (see addEventListener ).

We filter out all the drag events whose target is not #button and also suppress any duplicates event with distinctUntilChanged .

We will need to do some math in order to tackle the latter.

event.clientY and event.clientX represent the position of the draggable button on the screen. Based on those, we need to calculate a number between 0 and 1 to be the opacity of the overlay.

We set the maximum values both x and y can be as window.innerHeight and window.innerWidth divided by 2, respectively. We normalize x and y , to be values between 0 and their maximum values. Finally, we calculate pY and pX (which will be values between 0 and 1), and set the opacity with the higher value.

4. Slide-out animation

In my experience, questions about how elements can be animated are very common. In this instance, I was asked to implement a slide-out animation without using CSS animations and transitions whenever an element is clicked.

Let’s start with the HTML:

<html>

<body>

<div id="box"></div>

</body>

<html>

And CSS:

#box {

width: 50px;

height: 50px;

background-color: blue;

}

There is more than one way to implement animations with Javascript. I recommend using window.requestAnimationFrame:

We added a click event listener so that every time #box is clicked, slideOut is called with the element and the duration of the animation.

The slideOut function defines the initial and the target values for the translateX transform. Creates a loop and invokes it using requestAnimationFrame . The loop will be executed until #box reaches the end of the screen. Every new value is calculated using a linear equation.

A usual follow up question is: how would you implement an easing function?

Luckily, we already have all the parameters we need to swap our linear equation with one of Penner’s equations. Let’s take easeInQuad:

easeInQuad = function (t, b, c, d) { return c*(t/=d)*t + b; };

We change line 9 to:

const value = target * (time / duration) * (time / duration) + initial;

And you can see the result here:

If you are interested in Javascript animations, I wrote an article about it:

5. Giphy client

For the last challenge we’ll look at, I was tasked to implement a little web application that allows users to search and browse gifs from the Giphy API.

I was given total freedom to pick whatever framework and libraries I felt most comfortable with. For this article, I’ll be using React and fetch .

Let’s start by creating a simple React component with a form that will handle user input:

If time allows, you should consider creating sub-components to keep your code organized. Usually, during an interview, time is against you. So, even if you don’t have time to do it, always let the interviewer know what you have in mind for making the code better.

Now, in order to consume the Giphy API, we need to generate an API key. Once we have it, we can add a function to our component to fetch the data from the search endpoint.

For the sake of simplicity, there’s no error handling for any API exceptions.

Now we need to make the <form> call the search method when the user clicks Search or hits ENTER.

<form

onSubmit={e => {

e.preventDefault(); // prevents the page from reloading

search();

}}

>

And finally, we augment our component to render gifs from the search results:

With some basic CSS, this is the result: