JavaScript Interview questions and Implementation

I've tried implementing a few famous JavaScript interview questions along with the resources to learn and a demo with code.

# Closures

Closures are functions that have access to their lexical environment.
Read more about closures in this tutorial

const CounterFactory = function() {
let counter = 0;
return {
getCount : () => counter,
increment : () => {counter++;},
decrement : () => {counter--;},
}
}
const counter = CounterFactory();
console.log(counter);

Here the object returned has functions that form closures with the reference to counter variable. Thus, whenever we call increment or decrement the counter variable's value is changed as it is referenced by position.
Below is a demo of the same.

The below demo could also be asked as an interview question as Implement a counter with increment & decrement functionality. Avoid using Global variables.

Count:

# Callback functions

Functions passed as arguments to other functions are called callback functions

function x(y){
console.log("X");
y();
}
function y(){
console.log("Y");
}
x(y);

Calling x(y) would log X and Y to the console.
Here, y is a callback function that is passed to x as an argument.

Clicking on the button below would call x(y). Check the console to see the log.

# Callback Queue & Main thread blocking

Callback functions can only be executed by the Javascript runtime engine when they are pushed in the call stack.


But they cannot be directly moved to the call stack. Instead, they are pushed to the callback queue after the
timeout expiers(in case setTimeout). A program called the event loop continously keeps track of the
callback queue and if there are any callback functions in the callback queue. It pushes the first one into the
call stack only if the call stack is empty.

If the callstack is not empty, the event loop would wait for the callstack to be empty and only then push the callback function into the call stack.

But there's another type of queue called the microtask queue which has higher priority than callback queue. All functions coming through promises and mutation observer are pushed into the callback queue.

This means functions into the microtask queue will always get higher priority even if there's function present in the callback queue.


function blocking() {
console.log("Start");

setTimeout(() => {
console.log("I was supposed to be called after 1s.")
console.log("setTimeout Callback func");
}, 1000);

console.log("End");

//Blocking the Main Thread
console.log("Started Blocking the Main Thread");
let startDt = Date.now();
let endDt = Date.now();

// till the endDt is 10s from the start time
// the loop keeps running on the main thread i.e. on the callstack
while (endDt < startDt + 10000) {
endDt = Date.now();
}
console.log("Successfully blocked the main thread for 10 seconds");
console.log("Ended Blocking the Main Thread");
}


After calling the function, a timeout is registered to be executed after 1 second.
But we are runing a while loop on the main thread for 10s. Thus,
after 1 second the callback function is pushed to the callback queue. But the
event loop is unable to push the callback function to the call stack and the
callback function is executed after 10 seconds once the call stack is empty.

to to run the above code and see the result in the console.

# First Class Functions

First class objects are called first class citizens. These objects have the following properties:
> Be stored in a variable;
> Be passed as arguments to functions;
> Be returned by functions;
> Be stored in some data structure; and,
> Hold their own properties and methods.
Functions have all these properties and hence are called First class functions.
Below are demos of the same.

# Arrow Functions


() => window.alert("Hi! from Arrow") // arrow funtion

# Debouncing & Throttling in JS

This Tutorial blog explains both these topics very clearly.

# Promises

Promises in javascript represent an eventual completion order failure of an asynchronous operation.
These asynchronous operations are called blocking code like file read/write, DB and API operations
that block the main thread if they are called synchronously.
Promises have 3 states Pending, Resolved and Rejected and they can live in either one of these states.

Creating a promise


const promise = new Promise(function (resolve, reject) {

if(/*operation Successful*/){
//resolve the promise
resolve(/*pass arguments*/)
}

else{ //operation failed
//reject the promise by specfying the error
reject(new Error("mention cause of error here"))
}

});

The promise variable holds a Promise object. And the state of this promise is Pending. Once the operation is complete( maybe some DB operation or API call) we either resolve the promise if the operation was successful or reject the promise if the operation failed.

Handling a Promise
A Promise will finally be either Resolved or Rejected. If a Promise is resolved then we chain a .then method and
pass a callback to the .then method than will be called after the promise is resolved. In case a Promise is rejected
then we chain a .catch method and pass a error handling callback to the .catch method.


// creating a promise object
const resolverPromise = new Promise(
function (resolve, reject) {
setTimeout(() => {
resolve("SDE Mayukh");
}, 1000);
});

resolverPromise.then((username) => window.alert("Welcome!! " + username));

rejectorPromise.catch((err) => window.alert("Unable to fetch data. " + err));

Follow me on Github

Follow me on Linkedin