Frequently asked JavaScript and Node.js interview questions

I have been helping a friend crack preliminary round of JavaScript/Node.js interviews. In the process I have identified a few must-know questions that are asked in almost all interviews.

So, here is a list of such Node.js interview questions with their answers that will help you crack basic JS interviews.

What is Node.js?

Node.js is a platform built on Chrome's V8 engine to run JavaScript on the server. It is a single-threaded event-based platform.

Why is Node.js Single-threaded?

Node.js applications use "Single Threaded Event Loop Model" architecture to handle multiple concurrent clients. Node.js works on Event Loop which is single threaded and uses multiple threads internally to execute asynchronous code. Node.js is non-blocking which means that all functions ( callbacks ) are delegated to the event loop and they are ( or can be ) executed by different threads ( worker threads ). So, if you make a synchronous call which is CPU intensive it will block the thread. Hence we go for an asynchronous call which has better performance and scalability when they are single-threaded over multi-threaded, making Node.js Single-threaded.

Why do people use Node.js?

Node.js allows you to build the entire website only in one programming language i.e JavaScript. Node.js can be used to build different types of applications such as regular web applications, real-time apps, REST API servers etc. It is preferred for the following reasons:

  • Fast: Node.js library is very fast in code execution.
  • Scalable: It is highly scalable because of its event mechanism which helps the server to respond in a non-blocking way.
  • Full Stack JS: People who are comfortable with JavaScript get to use the same language across the whole stack (which means more code reuse)

Some libraries/frameworks that are commonly used by Node.js developers:

  • express
  • fs
  • moment
  • lodash
  • mongoose
  • async
  • isomorphic-fetch
  • passport
  • cookie-parser
  • jest/morgan

and there are many more. You should ideally keep your own list of favorite npm modules.

Explain callback in Node.js.

A callback is simply a function you pass into another function so that it can be called at a later time.

function cbExample(val, callback){
    if(val == 1){
        callback(true);
    }else{
        callback(false);
    }
}

cbExample(0, 
//the anonymous function below defines the functionality of the callback
function (bool) {
    if (bool) {
        //do something
    } else {
        //do something
    }
});

What is error-first callback?

It is a pattern where a callback function takes an Error object as first parameter and result object as second.

Example:

fs.readFile(path, function(err, data) {  
  if (err) {
    // handle the error
    return console.log(err)
  }
  // use the data object
  console.log(data)
})

What is callback hell and how can you avoid it?

Callback hell is heavily nested callbacks which make the code unreadable and difficult to maintain.

const verifyUser = function(username, password, callback){
   db.verifyUser(username, password, (error, userInfo) => {
       if (error) {
           callback(error)
       }else{
           db.getRoles(username, (error, roles) => {
               if (error){
                   callback(error)
               }else {
                   db.logAccess(username, (error) => {
                       if (error){
                           callback(error);
                       }else{
                           callback(null, userInfo, roles);
                       }
                   })
               }
           })
       }
   })
};

We can avoid callback hell by :

  • modularization: breaking callbacks into small independent functions
const verifyUser = function(username, password) {
   db.verifyUser(username, password)
       .then(userInfo => db.getRoles(userInfo))
       .then(rolesInfo => db.logAccess(rolesInfo))
       .then(finalResult => {
           //do whatever the 'callback' would do
       })
       .catch((err) => {
           //do whatever the error handler needs
       });
};

const getRoles = new function (userInfo) {
   return new Promise((resolve, reject) => {
       db.connect()
           .then((connection) => connection.query('get roles sql'))
           .then((result) => resolve(result))
           .catch(reject)
   });
};
  • using async module: async provides straight-forward, powerful functions for working with asynchronous JavaScript
  • using generators with Promises
'use strict';

const fs = require('fs');

function readFile(file, encoding) {
  return new Promise((resolve) => {
    fs.readFile(file, encoding, (err, data) => {
      if (err) throw err;

      resolve(data);
    })
  });
}

function* processFile(inputFilePath, encoding) {
  try {
    const text = yield readFile(inputFilePath, encoding);
    const processedText = text.toUpperCase();
    return processedText;
  } catch (e) {
    console.error(String(e));
  }
}

function execute(generator, yeildValue) {
  const next = generator.next(yeildValue);

  if (!next.done) {
    next.value.then(result => execute(generator, result))
              .catch(err => generator.throw(err));
  } else {
    console.log(next.value);
  }
}

execute(processFile('./input1.txt', 'utf-8'));
  • use async/await
const verifyUser = async function(username, password){
   try {
       const userInfo = await db.verifyUser(username, password);
       const rolesInfo = await db.getRoles(userInfo);
       const logStatus = await db.logAccess(userInfo);
       return userInfo;
   }catch (e){
       //handle errors as needed
   }
};

What is a Promise?

A promise is an object whose value is not available yet but will be available in future. This returned value can be a resolved value or a reason depicting why it is rejected. It will be in one of 3 possible states:

  • Fulfilled: resolve() was called
  • Rejected: reject() was called
  • Pending: not yet fulfilled or rejected
var promise = new Promise(function(resolve, reject) {
  setTimeout(function() { //simulate an async call
    resolve('foo');
  }, 300);
});

promise.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

What are modules and what is the purpose of module.exports in Node.js?

Modules are a reusable block of code whose existence does not impact other code in any way. It encapsulates related code into a single unit of code. Modules are important for maintainability, reusability, and namespacing of code.

module.exports = {

    sayHelloInEnglish: function() {
        return "Hello";
    }
    sayHelloInHindi: function() {
        return "Namaste";
    }
}

Here module.exports exposes two functions to the outer world. We can import and use these functions.

var greetings = require("./greeting.js");
greetings.sayHelloInHindi(); //Namaste

Explain in brief the difference among setInterval(), setTimeout(), setImmediate() and process.nextTick().

setInterval(): As the name suggests it can be used to execute a block of code multiple times in fixed intervals.

const intervalObj = setInterval(() => {
  console.log('Execute multiple times');
}, 500);

clearInterval(intervalObj);

setTimeout(): It can be used to schedule code execution after a designated amount of milliseconds.

const timeoutObj = setTimeout(() => {
  console.log('timeout beyond time');
}, 1500);

clearTimeout(timeoutObj);

setImmediate(): It is used to execute code at the end of the current event loop cycle.

const immediateObj = setImmediate(() => {
  console.log('immediately executing immediate');
});

clearImmediate(immediateObj);

process.nextTick(): It can be used to schedule a callback function to be invoked in the next iteration of the event loop.

It's worth noting that process.nextTick() fires more immediately than setImmediate().

function cb(){
  console.log('Processed in next iteration');
}
process.nextTick(cb);
console.log('Processed in the first iteration');
//Processed in the first iteration'
//Processed in next iteration

What are some different ways to do ajax calls in JavaScript?

In the interviews, interviewers often ask to write different types of ajax calls in JavaScript. Refer to the article to know more about different ways to do Ajax calls in JavaScript.

What are some interesting ES6 features?

Default Parameters:

In ES5, the default value is specified inside a function like this:

var link = function (height, color, url) {
    var height = height || 50
    var color = color || 'red'
    var url = url || 'https://hashnode.com'
    ...
}

In ES6, we can put the default values in the function params, right next to the passing arguments:

var link = function(height = 50, color = 'red', url = 'http://hashnode.com') {
  ...
}

Template Literals:

Template literals or interpolation in other languages is a way to output variables in the string.

In ES5,

var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id

In ES6, we can use ticked string as following:

var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`

Multi-line Strings:

In ES5,

var books = 'THE MURDER OF ROGER ACKROYD,\n\t'
                          + 'MURDER ON THE ORIENT EXPRESS,\n\t'
                            + 'AND THEN THERE WERE NONE,\n\t'
                              + 'A MURDER IS ANNOUNCED,\n\t'
                                + 'FIVE LITTLE PIGS\n\t'

In ES6, backticks come to rescue,

var books = `THE MURDER OF ROGER ACKROYD,
MURDER ON THE ORIENT EXPRESS,
AND THEN THERE WERE NONE,
A MURDER IS ANNOUNCED,
FIVE LITTLE PIGS`

Arrow Functions:

Arrow functions provide a more concise syntax for writing function expressions. Arrow functions do not have this. If this is accessed, it is taken from the outside (outer scope).

// (param1, param2, paramN) => expression

// ES5
var addES5 = function(x, y) {
  return x + y;
};

// ES6
const addES6 = (x, y) => { return x + y };

//No parameter

//ES5
var functionES5 = function someFunc() {
    console.log("Hello");
};

//ES6
var functionES6 = () => { console.log("Hello"); };
functionES6(); // Hello

Let and Const

In ES5, variables are declared using var (global scope). In ES6, block scoped let and const is used to declare variables.

Let's see the difference between var, let and const.

function differenceVar(){
  var a =10;
  console.log(a);  // output 10
  if (true) {
   var a=20;
   console.log(a); // output 20 //overriding an existing value
  }
  console.log(a);  // output 20
}

//The let statement declares a local variable in a block scope.
function differenceLet(){
  let a =10;
  console.log(a);  // output 10
  if (true) {
   let a=20;
   console.log(a); // output 20
  }
  console.log(a);  // output 10
}

In case of const the value can be assigned to a variable only once and they can't be changed.

function differenceConst(){
  const MY_VARIABLE = 10; //declaration and initialization are to be done at the same time
  console.log(MY_VARIABLE);  // output 10 
}

Variables declared with let and const remain uninitialized at the beginning of execution whilst variables declared with var are initialized with a value of undefined.

What is the difference between undefined and not defined or Reference Error?

In JavaScript, an undeclared variable is assigned the value undefined at execution and is also of type undefined.

console.log(typeof a); // undefined

A ReferenceError is thrown when we try to access a previously undeclared variable.

console.log(a); // ReferenceError: variable is not defined

What do you mean by hoisting?

Functions and variables that are declared anywhere in the code are moved to the top of the scope due to hoisting.

Note: Only declarations are moved, assignments are left in place.

We should make a habit to declare and initialize JavaScript variables before use. Using strict mode in JavaScript ES5 can help expose undeclared variables.

function foo() {
    var a; // a is hoisted at the top of foo()
    console.log(a); // undefined
    a=2;
}
foo();
foo(); // not Reference Error but TypeError
var foo = function bar() {
....
}

Here foo() is attempting to invoke the undefined value, which is TypeError. Function declarations are hoisted but function expressions are not.

What do you mean by closure?

Closure happens when a function is able to access a variable defined in its enclosing (outer) scope.

The closure has access to variables in three scopes:

  • Variables declared in their own scope
  • Variables declared in a parent function scope
  • Variables declared in the global namespace
function adder(num) { 
    var amount = 5;
    return function () {
        return amount + num;
    }
}

var sum = adder (3);
var output = sum();
console.log(output); //8

What is the difference between .call() and .apply()?

Both call and apply help execute functions. The difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);
// expected output: "cheese"
var numbers = [5, 6, 2, 3, 7];

var max = Math.max.apply(null, numbers);

console.log(max);
// expected output: 7

var min = Math.min.apply(null, numbers);

console.log(min);
// expected output: 2

What is undefined x 1 in JavaScript?

undefined Γ— 1 is just way of displaying an array's uninitialized index in Chrome's developer console.

var fruits = ["Strawberry", "Banana", "Mango", "Kiwi", "Orange"]
delete fruits[3];

Output of fruits will be: ["Strawberry", "Banana", "Mango", undefined Γ— 1, "Orange"]

How do you add an element to the beginning of an array? How do you add one at the end?

var myArray = ['a', 'b', 'c', 'd'];
myArray.push('end');
myArray.unshift('start');
console.log(myArray); // ["start", "a", "b", "c", "d", "end"]

In ES6, we can use spread operator

myArray = ['start', ...myArray, 'end'];

What are self-executing functions or IIFE?

IIFE (Immediately Invoked Function Expressions) functions are executed right after its definition. It is a design pattern which is also known as a Self-Executing Anonymous Function and contains two major parts. The first is the anonymous function with lexical scope enclosed within the Grouping Operator (). This prevents accessing variables within the IIFE idiom as well as polluting the global scope.

The second part creates the immediately executing function expression () through which the JavaScript engine will directly interpret the function.

Example:

(function(){
    console.log('In IIFE');
})();

Note : The function becomes a function expression which is immediately executed. The variable within the expression cannot be accessed from outside it.


I hope this helps people who are preparing for JavaScript and Node.js interviews. If I have left any basic questions, feel free to comment. I am considering making a part two if this gets traction. :)

Software Developer πŸ‘©πŸΌβ€πŸ’» Foodie πŸ˜‹ Explorer πŸ•΅οΈβ€β™€οΈ Dog lover 🐢

Write your comment…

5 comments

Nicely done !!! waiting for part2.

Reply to this…

Share your programming knowledge and learn from the best developers on Hashnode

Get started

Nice overview! I think many of these would give a useful indication of whether someone knows js.

Why is Node.js Single-threaded?

Your answer explains what is single-threaded about it. But why did they choose or have to make it single threaded?

What are self-executing functions or IIFE?

Here too I would focus more on what the point of it is, rather than memorizing abbreviations.

Thanks @mverleg for the comments. I will describe it in detail. πŸ™‚

Reply to this…

Thanks for this!

Reply to this…

I knew already everything you have mentioned. Oh My god Am I master in JS πŸ€·β€β™‚οΈπŸ€·β€β™‚οΈπŸ€·β€β™‚οΈ πŸ˜‚πŸ˜‚πŸ˜‚

Anyway Nice one dude, Keep writing.

Reply to this…