Categories
JavaScript Interview Questions

JavaScript Interview Questions — Tricky Questions

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at various kinds of questions that may throw anyone off.

Accidental Global Variable Creation

What are the values that are logged in the console log in the code snippet below?

function foo() {
  let a = b = 0;
  a++;
  return a;
}

foo();

console.log(typeof a);
console.log(typeof b);

typeof a should return 'undefined' so the first console.log is 'undefined' .

However, the second console.log logs 'number' since b is a global variable.

Don’t let the let keyword fool us, b is still a global variable since it has no keyword before it.

b = 0 is the same as window.b = 0 .

To avoid this tricky situation, use strict mode by adding 'use strict' to the top of out code. Then we’ll get the error ‘b is not defined’.

Modules always use strict mode so this is not an issue with them.

Array Length Property

What does the console log on the last line display in the code below?

const fruits = ['apple', 'orange'];
fruits.length = 0;

fruits[0];
console.log(fruits[0])

The console.log should show undefined since we set the fruits ‘s length property to 0, which empties the array.

Therefore, fruits becomes an empty array set setting its length to 0.

Then we display undefined .

Tricky Numbers Array

What does the console log in the code snippet below log?

const length = 4;
const numbers = [];
for (var i = 0; i < length; i++); {
  numbers.push(i + 1);
}

console.log(numbers);

The numbers array should be [5] since i is incremented without running anything since we have:

for (var i = 0; i < length; i++);

and then we have:

{
  numbers.push(i + 1);
}

So we have a for loop that did nothing but increment i and a block that pushes i + 1 to numbers .

The var keyword makes i available outside the for loop. Therefore, we can push i + 1 , which is 5, since i is 4.

Therefore, numbers is [5] .

If we replace var with let , then we won’t have this issue since we’ll get an error when we push as i won’t be available outside the for loop.

Automatic Semicolon Insertion

What does the console log on the last line display?

function foo(item) {
  return
    [item];
}

console.log(foo(5));

It should display undefined since we ran return with nothing returned since a semicolon is automatically inserted on the last line in JavaScript.

[item] is therefore never ran.

To make sure that we don’t make this mistake, we should put whatever we return on the same line as the return keyword.

Tricky Closure

What does the following code display in the console?

let i;
for (i = 0; i < 5; i++) {
  const log = () => {
    console.log(i);
  }
  setTimeout(log, 100);
}

The code above should log 5 five times since setTimeout runs the log function after the for loop is done.

setTimeout is async, so it’s queued in the event loop and runs when all the synchronous code is done running.

Therefore, first the for loop runs and creates a new log function, which captures the variable i .

Then the setTimeout schedules it to be run after the for loop is done.

Then the log function runs after the loop is done when i is 5.

After 100 milliseconds, the 5scheduled log callbacks are called by setTimeout .

log reads the current value of i , which is 5 and runs log with that value.

We can fix this by passing in i to log so that the value of i that’s currently being loop through is preserved in log as follows:

let i;
for (i = 0; i < 5; i++) {
  const log = (i) => {
    console.log(i);
  }
  setTimeout(log, 100, i);
}

All arguments after the 2nd argument are passed into setTimeout are passed into the callback and are accessible via the parameters.

Conclusion

We should be aware of accidentally creating global variables in scripts. Any variables that don’t have a keyword before it is a global variable.

Also, we can create loops that have no blocks below it in JavaScript, so should be careful of not to insert a semicolon between the closing parentheses and the opening curly brackets.

When we want to return a value, we should put whatever it is right after the return keyword.

Finally, if we want a value inside a setTimeout callback when setTimeout is called inside a loop, then we should pass it into the callback so the current loop value is preserved.

Categories
JavaScript Interview Questions

Basic JavaScript Interview Exercises — Numbers and Elements

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some quick warmup questions that everyone should know.

Write a function that computes the Fibonacci number of N.

We can do that with a loop and the destructuring syntax of JavaScript.

We create the fib function as follows:

const fib = (n) => {
  let i = 1,
    a = 1,
    b = 1;
  while (i < n) {
    [a, b] = [b, a + b];
    i++;
  }
  return a;
}

In the code above, we set b to a and b to a + b to update the numbers with the new Fibonacci values as we increase i .

Then we return a when we’re done with the loop.

Write a function that accepts a string and returns a map with the strings character frequency.

We can use a JavaScript Map to do this.

We count the frequencies of the characters in a string by splitting it into an array of characters and then counting the frequency of the characters as follows:

const count = str => {
  const chars = str.split('');
  const frequencies = new Map();
  for (let c of chars) {
    const freq = frequencies.get(c) || 0;
    frequencies.set(c, freq + 1);
  }
  return frequencies;
}

In the code, we used the Map ‘s get method to get the frequency, and we add it by 1 and then set it.

Once we’re done with the loop, we return the Map .

Write a function that accepts a number and checks if it’s a prime or not.

We can check if a number is a prime by checking if it’s 2 or odd. If it’s odd, then we try to divide numbers up to the floor of the given number divided by 2.

For example, we can write the following function to check for prime numbers:

const isPrime = (num) => {
  if (num % 2 === 0 && num !== 2) {
    return false;
  }
  for (let i = 3; i <= Math.ceil(num / 2); i++) {
    if (num % i === 0) {
      return false;
    }
  }
  return true
}

We check if it’s even and it’s not 2. If it is, we return false .

Otherwise, we run the loop to check if a number is divisible by 3 up to the ceiling of the num divided 2.

If it’s evenly divisible by any of those, then we return false .

Otherwise, we return true .

Write a function that accepts a DOM element and a string and prints any of its immediate children that contain the class name with that string.

We can use the getElementsByClassName method of an element object to get the children with the given class attribute.

For instance, we can write the following function:

const getChildrenWithClass = (el, className) => {
 const children = el.getElementsByClassName(className);
  for (let c of children) {
   console.log(c);
  }
}

The code above calls the getElementsByClassName on the el element object and prints out the child elements with the given class name.

Also, we can use the querySelectorAll method to do the same thing.

We can write the following:

const getChildrenWithClass = (el, className) => {
  const children = el.querySelectorAll(`.${className}`);
  for (let c of children) {
    console.log(c);
  }
}

The only difference is that we called querySelectAll with the template string `.${className}` .

Write a function that accepts a DOM element and a string and prints if any of its parent nodes contain the class with that string. It should stop when there are no parent elements.

We can use the parentNode property recursively until we reach the root element or until we find the element with the className that we wanted.

To do this, we create a getParentWithClassName as follows:

const getParentWithClassName = (el, className) => {
  let currentEl = el.parentNode;
  while (currentEl) {
    if (currentEl.className === className) {
      return currentEl;
    }
    currentEl = currentEl.parentNode;
  }
  return undefined;
}

In the code above, we set currentEl to the parentNode of el .

Then we use a while loop through to search for a parentNode with the given className until we find one with the given name.

If we find one with the given className , we return the element.

Otherwise, we keep going by setting currrentel to currentEl.parentNode .

If we loop up to the root node and still didn’t find an element with the given className , we return undefined .

Conclusion

We use the parentNode property to find the parent of a child node.

To get the child node with the given CSS selector, we can call any DOM navigation methods to find the elements with the given selector.

To create a dictionary we can use the Map constructor.

We can use the destructuring syntax to reassign multiple things easily as we did with the Fibonacci numbers.

Categories
JavaScript Interview Questions

Basic JavaScript Interview Exercises

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some quick warmup questions that everyone should know.

Write a function the reverses a string

We can use JavaScript’s string and array methods to reverse a string easily.

To do this, we can write the following function:

const reverseString = (str) => str.split('').reverse().join('');

The function works by splitting the string into an array of characters, then reversing the array, and joining it back together.

We used JavaScript string’s split method and array’s reverse and join methods.

Write a function that filters out numbers from a list.

We can do that with the isNaN function and the array’s filter method.

To solve this problem, we can write the following code:

const removeNums = (arr) => arr.filter(a => isNaN(+a));

In the removeNums function, we pass in an array arr then call filter on it with a callback that returns isNaN(+a) , which is true if an item is converted to NaN when we try to convert it to a number.

Write a function that finds an element inside an unsorted list.

We can use the array’s findIndex method to find an element inside an unsorted list.

We write the following function:

const search = (arr, searchItem) => arr.findIndex(a => a === searchItem);

to do the search. The findIndex method returns the index of the first item that it finds that meets the condition in the callback.

We can use it as follows:

console.log(search(['foo', 'bar', 1], 'foo'));

to search for the string 'foo' . We then should get 0 since 'foo' is the first entry in the array.

Write a function that showcases the usage of closures.

A closure is a function that returns a function. It’s usually used to hide some data inside the outer function to keep them from being exposed from the outside.

We can do that by writing:

const multiply = (first) => {
  let a = first;
  return (b) => {
    return a * b;
  };
}

Then we can call it by writing:

console.log(multiply(2)(3));

which gets us 6.

What is a Promise? Write a function that returns a Promise.

A promise is a piece of asynchronous code that runs in an indeterminate amount of time.

It can have the pending, fulfilled or rejected states. Fulfilled means it’s successful, rejected means that it failed.

An example of a promise is the Fetch API. It returns a promise and we can use it to return a promise ourselves.

For instance, we can write:

const getJoke = async () => {
  const res = await fetch('http://api.icndb.com/jokes/random')
  const joke = await res.json();
  return joke;
}

to get a joke from the Chuck Norris API.

Write a function that flattens a list of items.

We can use the array flat method to flatten a an array of items.

For example, we can write:

const flatten = arr => arr.flat(Infinity);

to flatten all levels of an array to one level.

We can also loop through each item of an array and recusively flatten nested arrays into one level.

For instance, we can write the following:

const flatten = (arr = []) => {
  let result = [];
  for (let item of arr) {
    if (Array.isArray(item)) {
      result = result.concat(flatten(item));
    } else {
      result = result.concat(item);
    }
  }
  return result;
}

to flatten the array.

The code works by looping through each entry of the array. Then find the arrays in the entries and the flatten calls itself then append it to result. Otherwise, it just adds the item into the result array.

After it went through all the levels, it returns result .

Write a function that accepts two numbers **a** and **b** and returns both the division of **a** and **b** and their modulo of **a** and**b**.

We can do that by using the / operator to divide a and b , and the % operator to find the remainder when we divide a by b .

To do that, we can write the following function:

const divMod = (a, b) => {
  if (b !== 0) {
    return [a / b, a % b];
  }
  return [0, 0];
}

We check if the divisor is zero, then we do the operations as we mentioned and return the computed items in an array.

Conclusion

We can use arrays and string methods as much as possible to make our lives easier.

They’re also more efficient than what we implement from scratch.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — DOM and Event Questions

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some harder questions about DOM manipulation and handling events.

What is a repaint and when does this happen?

A repaint happens when we change the look of an element without changing its size and shape.

It doesn’t cause reflow since its dimensions and position didn’t change.

The repainting process happens when an element changes the background color, change text color, or hide visibility.

How could we run some JavaScript when DOM is ready like $(document).ready?

We can put our scripts in the HTML body element. The DOM would be ready by the time the browser runs the script tag there.

Also, we can put our code inside the DOMContentLoaded event handler. The code inside will run only when the DOM is completely loaded.

For example, we can write the following:

document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM loaded');
});

We can also watch the readystatechange event by attaching a listener to it.

When the readyState is 'complete' , then we know the DOM has loaded.

For instance, we can write the following code to do that:

document.onreadystatechange = () => {
  if (document.readyState == "complete") {
    console.log('DOM loaded');
  }
}

What is event bubbling? How does event flow?

Event bubbling means that the event propagates from the originating element to its parent, grandparent, and all the way up to the window object.

The browser will run all event handlers that are attached to all the parent elements of the originating element in addition to the originating element.

For example, if we have the following HTML:

<div>
  <p>
    <button>Click</button>
  </p>
</div>

Then when we attach event listeners to all the elements and document and window as follows:

const div = document.querySelector('div');
const p = document.querySelector('p');
const button = document.querySelector('button');

button.onclick = () => {
  alert('button clicked');
}

p.onclick = () => {
  alert('p clicked');
}

div.onclick = () => {
  alert('div clicked');
}

document.onclick = () => {
  alert('document clicked');
}

window.onclick = () => {
  alert('window clicked');
}

and click the Click button, then we’ll see all the alerts listed in the same order that we listed in the code.

So we get ‘button clicked’, ‘p clicked’, ‘div clicked’, ‘document clicked’ and ‘window clicked’ alerts displayed in that order.

How would we destroy multiple list items with one click handler?

We can use event delegation to do that.

It works by listening to the clicks of the parent element of the list. Then we can check which child has been clicked in the click handler and then remove that element from the DOM.

For example, if we have the following HTML:

<ul>
    <li>first</li>
    <li>second</li>
    <li>third</li>
    <li>forth</li>
    <li>Fifth</li>
</ul>

Then we can write the following JavaScript code to remove the li elements that we clicked on as follows:

document.querySelector('ul').addEventListener('click', (e) => {
  const elm = e.target.parentNode;
  elm.removeChild(e.target);
  e.preventDefault();
});

In the code above, we get the parentNode property of the element we clicked on to get the ul.

Then we can call removeChild on it to remove the li that we clicked on since e.target is the element that we clicked on, which is the li.

Finally, we call preventDefault to stop event propagation.

Create a button that is destroyed by clicking on it but two new buttons are created in its place.

We can do that by using the logic above for removing the button that we clicked on.

Then we add use createElement and appendChild to create more buttons and add them to the list.

For example, given the following HTML:

<div>
  <button>button</button>
</div>

We write the following JavaScript code to add 2 buttons and then remove the original button that was clicked on by attaching a click listener to the div and then manipulating the buttons:

document.querySelector('div').addEventListener('click', (e) => {
  if (e.target.tagName === 'DIV') {
    return;
  }
  const elm = e.target.parentNode;
  e.preventDefault();

  const btn = document.createElement('button');
  btn.innerHTML = 'button';

  const btn2 = document.createElement('button');
  btn2.innerHTML = 'button';

  elm.appendChild(btn);
  elm.appendChild(btn2);
  elm.removeChild(e.target);
});

In the code above, we check if we actually clicked on a button.

If we did, then we proceed to create 2 buttons. Then we call appendChild on the parentNode of the button that was clicked, which is the div, to attach the 2 buttons.

Then we call removeChild on e.target , which should the button since we checked it’s not a div, to remove the button.

Conclusion

We can watch if the DOM is ready with readystatechange or DOMContentLoaded events.

Event bubbling happens when an element’s events propagate up the DOM tree.

appendChild and removeChild are used to add and remove elements. We can handle events of multiple child elements with event delegation.

A repaint happens when we change the look of an element without changing its geometry.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Theory

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some theoretical questions about JavaScript

Name two programming paradigms important for JavaScript app developers.

JavaScript supports both object-oriented programming (OOP) with some functional programming concepts added in.

JavaScript supports OOP via prototypical inheritance.

The JavaScript class syntax is just syntactic sugar on top of its prototypical inheritance model.

Functional programming concepts that are part of JavaScript include closures, first-class functions, and anonymous functions.

Where is functional programming concepts used in JavaScript?

Functional programming concepts include pure functions, which are functions that avoid side effects, composing functions, and passing functions as arguments since functions are first class.

The immutability of objects are also important with functional programming to avoid bugs from multiple entities changing the same object.

What is the difference between classical inheritance and prototypal inheritance?

Language with class inheritance has classes that are blueprints for creating objects.

We can also have subclasses that are children of a parent class. Therefore, there is a class hierarchy.

Instances of the class are created with the new operator.

Prototypical inheritance is where instances of an object directly inherit from a prototype object.

Instances are generally created from factory functions. Instances may be composed of many different objects.

JavaScript uses prototypical inheritance despite the use of the new operator.

The new operator is used with constructor functions, which are factory functions that are used to create new instances of objects.

The class syntax is the same as a constructor function. JavaScript doesn’t use class-based inheritance despite the use of the class syntax.

JavaScript classes are still constructor functions with a cleaner, more easily understood syntax.

What are the pros and cons of functional programming vs object-oriented programming?

OOP is easy to understand and the basic concepts of objects are easy.

Therefore, it’s easy to interpret to the meaning of its members.

OOP uses an imperative style of programming rather than a declarative style. Imperative programming means that statements are used to change a program’s state.

Declarative programming describes logic without describing the control flow.

OOP depends on shared state. Objects and behaviors are put together into one entity. The members of the entity may be accessed in any more.

This may lead to issues like race conditions.

Functional programming uses pure functions to avoid any side effects. This eliminates bugs from multiple functions changing the same resource.

Functions tend to be simplified and composable for more reusable code compared to OOP.

Functional programming generally uses declarative styles, which do not write out everything step by step.

This means there’s more room for refactoring and we can replace algorithms with more efficient ones more easily.

Because of its declarative style, functional programming code is harder to read since not everything is written out line-by-line.

Functional programming also has more academic material than OOP materials since OOP has more materials targeted at beginners because of its popularity.

When is classical inheritance an appropriate choice?

Classic inheritance is only appropriate for a single level of inheritance. Multiple levels of inheritance is always an antipattern.

Multiple levels are confusing and hard to read.

Object composition is better than inheritance.

When is prototypal inheritance an appropriate choice?

Prototypical inheritance is useful since it allows for composition.

This means that objects can have the has-a, uses-a or can-do relationship, as opposed to the is-a relationship with class inheritance.

We can compose objects from multiple sources with prototypical inheritance and use mixins or Object.assign to combine multiple objects into one.

What does “favor object composition over class inheritance” mean?

Code should be assembled from smaller units of functionality into new objects instead of inheriting from classes and creating object taxonomies.

This means that instead of an is-a relationship, they can have a can-do, has-a, or uses-a relationships.

With composition, we avoid class hierarchies, tight coupling, and rigid taxonomy.

It also makes code more flexible.

What is asynchronous programming, and why is it important in JavaScript?

JavaScript has a single-threaded runtime environment. That means that all synchronous code will block the main execution thread.

Long-running networking requests and I/O operations will prevent the rest of the app from running.

Asynchronous programming means that the engine runs in an event loop. Blocking operations are queued in the event loop instead of running immediately. Therefore, the code won’t block the rest of the code from running.

When the response is ready, then the event handler runs and the control flow for the asynchronous code continues.

This way, a single program thread can handle many concurrent operations.

Browser JavaScript environment and Node.js are both async by default.

Conclusion

It’s important to know that JavaScript is both an object-oriented and functional language.

Objects are composed of inheriting from prototype objects instead of having a rigid class hierarchy. The class syntax doesn’t make that any different.

Objects are created from constructor functions.

JavaScript is a single-threaded language, so concurrent operations have to be run asynchronously to preventing blocking the main thread.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.