Skip to content

Sushmita-Ghosh/javascript_interview_practice

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

javascript_interview_practice

This repository contains interview questions for javascript

Practice questions for Javascript Interview:

Apurv's List

TABLE OF CONTENTS:

Serial No Topic Name
1 DEBOUNCING
2 MEMOIZATION
3 SPREAD VS REST
4 WHAT IS ES6 AND ITS FEATURES
5 CLOSURES
6 CALL, APPLY, BIND
7 MAP, FILTER, REDUCE
8 UNDEFINED, NOT DEFINED
9 PROTOTYPES
10 MAP, SET, WEAKMAP, WEAKSET
11 HOISTING
12 EVENT BUBBLING, CAPTURING, PROPAGATION
13 CURRYING, INFINITE CURRYING
14 THROTTLING
15 THIS KEYWORD
16 PROMISES
17 ASYNC VS DEFER
18 HOW DO WE ACHIEVE ASYCNHRONOUS ACTIVITY IN JS? EVENT LOOP
19 ASYNC AWAIT
20 PROMISE CHAINING AND ERROR HANDLING
21 DELETE OPERATOR
22 SHALLOW COPY VS DEEP COPY

TOPICS:


DEBOUNCING


Limits the exceution of a function call , and waits for a certain amount of time before calling it again.

For example : Search Box - in application - here the number of calls to the api are limited by applying a delay so we can reduce the overhead on the server, and limit the number of api calls to the server.

Code :

For below code to work use npm install lodash

Debouncing.jsx

import { useState } from "react";
import debounce from "lodash/debounce";

function Debouncing() {
  const [pressedCount, setPressedCount] = useState(0);
  const [triggerCount, setTriggerCount] = useState(0);

  const onButtonClick = () => {
    setPressedCount(pressedCount + 1);
    debouncedCount();
  };

  const debouncedCount = debounce(() => {
    setTriggerCount(triggerCount + 1);
  }, 800);
  return (
    <>
      <button onClick={onButtonClick}>Increment</button>
      <p>
        Button Pressed <span>{pressedCount}</span> times
      </p>
      <p>
        Triggered <span>{triggerCount}</span> times
      </p>
    </>
  );
}

export default Debouncing;

App.jsx

import "./App.css";
import Debouncing from "./components/Debouncing";

function App() {
  return (
    <>
      <Debouncing />
    </>
  );
}

export default App;

Debouncing Polyfill

const myDebounce = (cb, wait) => {
  let timer;

  return function (...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      cb(...args);
    }, wait);
  };
};

const debouncedCount = myDebounce(() => {
  setTriggerCount(triggerCount + 1);
}, 800);

Blog YT


THROTLLING


Throlling is a mechanism to limit the execution of a even handler function when events are triggered continuously due to user action- like click of a button

For example : Say on scroll we are triggering an event which calls an Api( so it is an expensive function) - we can limit the calls of the event by using throllling function.

Code :

Throttling Pollyfill

const myThrottle = (cb, delay) => {
  let last = 0;

  return (...args) => {
    let now = new Date().getTime(); // we get current time
    if (now - last < delay) return; // if the current time - last time we triggeres < delay we return
    last = now; // if it is greater set the last to current time , triggered time
    return cb(...args); // execute the callback we return
  };
};

const throttledCount = myThrottle(() => {
  setTriggerCount(triggerCount + 1);
}, 1000);

YT


CURRYING, INFINITE CURRYING


- Currying is a concept in javascript wherein there is function that takes in one input at a time and returns a new function expecting the next input.
  • It is a convertion of funtions from callable as f(a,b) -> to f(a)(b)

-Basically Currying doesn’t call a function. It just transforms a function. They are constructed by chaining closures by immediately returning their inner functions simultaneously.

function f(a, b) {
  console.log(a, b);
}

function f(a) {
  return function (b) {
    console.log(a, b);
  };
}

f(4)(5);

Why do we need currying?

  • To avoid passing the same variable again & again
  • to create higher order func
  • to make your function pure and less prone to error.
  • It is a checking method that checks if you have all the things before you proceed.
  • It divides one function into multiple functions so that one handles one set of responsibility.

CLOSURES


Lexical Scope

Lexical scope means a variable defined outside a function can be accessible within a function but opposite is not true, variables declared inside function caanot be accessed outside

CLOSURE

  • A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).
  • In other words, a closure gives you access to an outer function's scope from an inner function.
  • In JavaScript, closures are created every time a function is created, at function creation time.

For example :

Code :

function makeFunc() {
  const name = "Sushmita";
  function displayName() {
    console.log(name);
  }
  return displayName;
}

//const myFunc = makeFunc();
//myFunc();

makeFunc()();

In the above example we are able to access the name which is defined in outer scope even after the function display name has been returned.

USE:

  • Closures make it possible for JS to have private variables.

What will be the output?

let count = 0(function printCount() {
  if (count === 0) {
    let count = 1; // shadowing
    console.log(count); // 1
  }
  console.log(count); // 0
})();

Output 1 0

Write a funtion that will allow you to do the below:

var addSix = createBase(6);
addSix(10); // 16
addSix(21); //27
function createBase(x) {
  return function (y) {
    console.log(x + y);
  };
}

TIME OPTIMIZATION

function find(index) {
  let a = [];
  for (let i = 0; i < 1000000; i++) {
    a[i] = i * i;
  }

  console.log(a[index]);
}

console.time("6");
find(6);
console.timeEnd("6");
console.time("12");
find(6);
console.timeEnd("12");

image

The above function is time consuming- We can use closures to optimize the time taken by them - The issue is that the looping is happening every time we are calling the function- as there is new reference to the a variable created everytime.

function find() {
  let a = [];
  for (let i = 0; i < 100000000; i++) {
    a[i] = i * i;
  }

  return function (index) {
    console.log(a[index]);
  };
}

const closure = find();
console.time("6");
closure(6);
console.timeEnd("6");
console.time("50");
closure(50);
console.timeEnd("50");

We are not doing the heaving operation - hence the time reduced is very very high as can be seen below - it is now in ms

image

HOW CAN WE SOLVE THE FAMOUS SETTIMEOUT QUES USING VAR?

for (var i = 0; i < 3; i++) {
  function inner(i) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000);
  }
  inner(i);
}

*The above code will create a new refernce to i each time the function inner is called.

PRIVATE COUNTER USING CLOSURE

function counter() {
  var _counter = 0; // Here counter is a private variable

  function add(increment) {
    _counter += increment;
  }

  function retrieve() {
    return "Counter = " + _counter;
  }

  return {
    add,
    retrieve,
  };
}

const c = counter(); // created a private counter
c.add(5);
c.add(10);

console.log(c.retrieve());
$ node script.js
Counter = 15

MODULE PATTERN

var Module = (function () {
  function privateMethod() {
    // do something which you do not want the user to access directly.
    // suppose we have an API call which we do not want to access to the iser, we can keep it here
  }
  return {
    publicMethod: function () {
      // can call the private Method
    },
  };
})();

Module.publicMethod(); // runs successfully
Module.privateMethod(); // give us an error

MAKE THE BELOW FUNCTION RUN ONLY ONCE:

let view;

function likeTheVideo() {
  view = "Sushmita Ghosh";
  console.log("Subscribe to " + view);
}

likeTheVideo();

*We can use closures to do the same - we can create a local variable "called" which will keep an count of how many time the function has run.

let view;

function likeTheVideo() {
  let called = 0;

  return function () {
    if (called > 0) {
      console.log("Already Subcribed to Sushmita's Channel");
    } else {
      view = "Sushmita Ghosh";
      console.log("Subscribe to " + view);
      called++;
    }
  };
}

let isSubscribed = likeTheVideo();
isSubscribed();
isSubscribed();
$ node script.js
Subscribe to Sushmita Ghosh
Already Subcribed to Sushmita's Channel

*Everytime we call the isSubscribed function we are referencing the same called variable.

ONCE POLYFILL:

  • We can write a more generic function for the above function.

CACHING & MEMOIZATION:

DIFFERENCE BETWEEN CLOSURE & SCOPE:

  • Whenever we create a function within another function, then the inner function is the closure. This closure is usually returned so that it can use the outer function's variable at a later time. ( Global, outer & local scopes)

  • A scope in js defined what variable you have access to - Local & global ( 2 kinds)

YT


THIS KEYWORD


THIS KEYWORD (IMPLICIT BINDING):

  • Depends on the context that we are refering to - based on which it's value changes.

THIS INSIDE FUNCTION:

  • For normal function this is taken - from the context to which it is referening to.
  • For arrow functions this refers to the outer normal function
  • In object method, this refers to object
  • alone, this refers to the global object
  • In a function, in strict mode, this is undefined
  • Array functions - map, filter, reduce - can access this.

For example :

Code :

let user = {
  name: "Sews",
  age: 24,
  getDetails() {
    console.log(this.name + " is " + this.age + " years old ");
  },
};

user.getDetails();
$ node this.js
Sews is 24 years old
let user = {
  name: "Sews",
  age: 24,
  childObj: {
    newName: "Suzuna",
    getDetails() {
      console.log(this.newName + " Nd " + this.name);
    },
  },
};

user.childObj.getDetails();
  • In the aboove funtion, this refers to "childObj response
$ node this.js
Suzuna is undefined years old
  • Replacing with Arrow Functions:

YT


CALL, APPLY, BIND


Code :

YT


PROMISES


SYNCHRONOUS CODE VS ASYNCHRONOUS CODE

  • line by line
  • js is a single-threaded language - it can't execute two tasks (like setTimeout) in parallel - what it does is it first runs all of our synchronous code and then setTimeout code will be executed
  • setTimeout is part of API - so even if the time given to setTimeout is 0ms, the order remains the same.
  • The above concept is of the event loop

WHAT ARE CALLBACKS?

  • Since JS is single-threaded, for any task where we need to wait for some time (asynchronous task) we do need callbacks
  • callbacks are functions which can be executed at a later point of time.
setTimeout(() => {
  console.log("Hello World");
}, 5000);

WHAT IS CALLBACK HELL/PYRAMID OF DOOM?

  • In a real-world application we might run into situations where we have a dependency of tasks on one another - say for example APIs trying to create order, payment, order summary, etc all these different APIs are dependent on one another but if we write the code - it gets ugly and difficult to understand. - which is called callback hell.

  • Callback nested within one another is callback hell, resulting in code growing horizontally.

  • This kind of structure is also known as the pyramid of doom.

WHAT IS INVERSION OF CONTROL?

Inversion of control is losing control over our code when using callbacks. Two issues while using callbacks

1 - Callback hell When a function is passed as an argument to another function, it becomes a callback function. This process continues and there are many callbacks inside another's Callback function. This grows the code horizontally instead of vertically. That mechanism is known as callback hell.

2 - Inversion of control The callback function is passed to another callback, this way we lose control of our code. We don't know what is happening behind the scenes and the program becomes challenging to maintain. That process is called inversion of control.

PROMISES:

  1. Before promise we used to depend on callback functions which would result in 1.) Callback Hell (Pyramid of doom) | 2.) Inversion of control

  2. Inversion of control is overcome by using promise. 2.1.1) A promise is an object that represents the eventual completion/failure of an asynchronous operation. 2.1.2) They are just syntactical sugar to the ugly code that callbacks bring into the picture. But under the hood all the working remains same. 2.2) A promise has 3 states: pending | fulfilled | rejected. 2.3) As soon as the promise is fulfilled/rejected => It updates the empty object which is assigned undefined in the pending state. 2.4) A promise resolves only once and it is immutable. 2.5) Using .then() we can control when we call the cb(callback) function. 2.6) A promise object has two things - PromiseState(pending/fulfilled) & PromiseData(data) 2.7) fetch returns a promise

  3. To avoid callback hell (Pyramid of doom) => We use promise chaining. This way our code expands vertically instead of horizontally. Chaining is done using '.then()'

  4. A very common mistake that developers do is not returning a value during chaining of promises. Always remember to return a value. This returned value will be used by the next .then() image

  1. A Promise is an object that represents the eventual completion or failure of an asynchronous operations.

  2. Importance of promise is that we do not loose the control of the program, a promise object is immutable and can be send anywhere without worrying about changes, also it resolves only once either to success or failure.

  3. How we initialise promise?

    let p = new Promise(function (resolve) {});
    console.log(p);
    Promise { <pending> }

CODE:

function myAsyncFn() {
  let p = new Promise(function (resolve) {
    resolve("hi there");
  });
  return p;
}

const value = myAsyncFn();
value.then(function (data) {
  console.log(value);
  console.log(data);
});

OUTPUT:

Promise { 'hi there' }
hi there

YT AKSHAY AKSHAY PROMISES


ASYNC VS DEFER


How does script loading happen in our webpage?

  • A html file as soon as it gets the script tag it starts to download and execute the js file. This will interrupt the html parsing causing an initial delay in html rendering and eventually time to load.

Async tag will start to download the js file parallely to html rendering but it blocks rendering after it is downloaded so blocking time is just the time it requires for executing and not downloading.

What happens when you add a async attribute?
  • Make par­al­lel requests to fetch the files.
  • Con­tinue pars­ing the doc­u­ment as if it was never interrupted.
  • Exe­cute the indi­vid­ual scripts the moment the files are downloaded.

Defer tag will parallely download the js file and will execute it once the html rendering is done. So no delay in html rendering.

What happens when you add defer attribute?
  • Make par­al­lel requests to fetch the indi­vid­ual files.
  • Con­tinue pars­ing the doc­u­ment as if it was never interrupted.
  • Fin­ish pars­ing the doc­u­ment even if the script files have downloaded.
  • Exe­cute each script in the order they were encoun­tered in the document.
When to use defer and async attributes on the <script> tag?

Defer attribute:It will guarantee all the scripts will execute after the HTML parsing.The defer attribute is useful when the script is used for DOM manipulations.

Async attribute: It does not guarantee that all the scripts will execute after the HTML parsing. The async attribute is useful when the script is not used for DOM manipulation (google ads link)

Which is the best place to place your script tag in the script file?
Async tag in the head tag?

The Async tag will always be independent so adding to the head also won't make it much more efficient.

Defer tag in head tag ?

Conventionally all tags are kept in body but keeping the script tag in head with defer will help a lot as during rendering, the js file will be downloaded parallelly and on completion of rendering js execution will start immediately ( we dont have to wait for js download again when rendering ends). This is kind of prefetching assets.

image

SAGAR GIRI'S POST


HOW DO WE ACHIEVE ASYCNHRONOUS ACTIVITY IN JS? EVENT LOOP


SINCE JS IS SINGLE-THREADED, HOW DO WE ACHIEVE ACHIEVE ASYCNHRONOUS ACTIVITY IN JS?

Even though JS is single-threaded ( just like the human brain). JS can do things parallelly by delegating the tasks & also context switch between tasks if need be( the net time to do both things would still be the same).

  • JS does this by using async functions.

WHAT IS ASYNCHRONOUS FUNCTION?

  • They are functions that can be executed parallelly with other sets of tasks probably after a certain amount of time. - eg setTimeout, fs.readFile( reads file from your system), fetch ( to fetch data from API endpoint)

Code :

function findSum(n) {
  let sum = 0;
  for (let i = 0; i < n; i++) {
    sum += i;
  }
  return sum;
}

function findSumTill100(n) {
  let sumTill100 = findSum(100);
  console.log(sumTill100);
}

setTimeout(findSumTill100, 1000);
console.log("hello world");

OUTPUT

hello world
4950

readFile

const fs = require("fs");

fs.readFile("a.txt", "utf-8", (err, data) => {
  console.log(data);
});

console.log("Will this be printed first?");

OUTPUT

Will this be printed first?
Hi There ! Hello from a.txt
  • 4 major things contribute to the async activity of JS: VISUALISE
    • Call Stack - responsible for running each line of code
    • Web Apis - provided by browser - have added functionality - not necessarily part of Javascript - In case of setTImeout - webapis help to execute the time frame - ie (number of miliseconds)
    • Callback Queue - once the wait is completed , it is pushed to the callback queue and it waits.
    • Event Loop - checks when the main thread is idle and it is pushed on to the callback stack to execute. It's job is to check if there is something in the callback queue - if yes puts to the call stack.

REAL USE OF CALLBACKS :

For synch code - without callbacks also we can suffice , but with asyn functions we need them


ASYNC AWAIT


Async Await is just syntactical sugar - also uses Promises and callbacks behind the hood.

CODE:

function myAsyncFunction() {
  let p = new Promise(function (resolve) {
    // do some async logic here
    setTimeout(function () {
      resolve("hi there!");
    }, 3000);
  });
  return p;
}

async function main() {
  const p = myAsyncFunction();
  console.log(p);
  const value = await myAsyncFunction();
  console.log(value);
}

main();
console.log("main");

OUTPUT:

Promise { <pending> }
main
hi there!

YT


PROMISE CHAINING AND ERROR HANDLING


PROMISE CREATION:

  • The .then part is how we consume promises, we can create our own promise as well.
  • promises can be created by calling the Promise constructor
  • the Promise constructor takes in two parameters - resolve & reject
  • as the name suggests we can resolve the promise when a condition is met and send the value - which can be accessible when we do a .then.
  • we can reject a promise and pass in a error to it.

Code :

  • Suppose we have a promise which creates an order ( which will have return an orderId) if it it gets resolved correctly or will be rejected if the cart does not meet the validations.
// Consuming the promise - generally we worry about this step.
const cart = ["shoes", "pants", "kurta"];

const promise = createOrder(cart); //orderID

promise.then(function (orderId) {
  console.log(orderId);
  // proceedToPayment(orderId);
});

// Creating the promise

function createOrder(cart) {
  const pr = new Promise(function (resolve, reject) {
    //  we will check if our cart is validated
    // if not we will reject the promise
    if (!validateCart(cart)) {
      const err = new Error("Cart is not valid");
      reject(err);
    }

    // once the cart is validated we can create an order and resolve with orderID
    const orderId = "12345";
    if (orderId) {
      resolve(orderId);
    }
  });

  return pr;
}

function validateCart(cart) {
  if (cart) {
    return true; // here we can check if cart is empty
  } else return false;
}
  • Till the time our promise is resolved - it will be in pending state
  • We can handle error using the .catch method , and we can pass a failure callback to it as well.
promise
  .then(function (orderId) {
    console.log(orderId);
  })
  .catch(function (err) {
    console.log(err);
  });

PROMISE CHAINING:

  • As the name suggests we can keep chaining our promises with the .then callback.
  • Each time we chain we can access the value of resolve of the previous promise passed onto the next.
  • One common mistake is - whatever we need to pass onto the chain we need to return it. - we can either return a value or the promise itself - which will be resolved.
const cart = ["apple", "banana"];

const promise = createOrder(cart); //orderID

promise
  .then(function (orderId) {
    console.log(orderId);
    return orderId;
  })
  .then(function (orderId) {
    return proceedToPayment(orderId);
  })
  .then(function (paymentInfo) {
    console.log(paymentInfo);
  })
  .catch(function (err) {
    console.log(err.message);
  });

function proceedToPayment(orderId) {
  return new Promise(function (resolve, reject) {
    resolve("Payment done successfully");
  });
}

YT


MAP, FILTER, REDUCE


MAP:

  • Map is used to iterate over the array and apply the callback function to each one and return a new array.

Code :

const nums = [1, 2, 3, 4];

const multiplyThree = nums.map((num, i, arr) => {
  return num * 3;
});

FILTER:

  • Applies the function as a conditional to the array - based on true from the condition the element is pushed onto the array.

Code :

const nums = [1, 2, 3, 4];

const moreThanTwo = nums.filter((num, i, arr) => {
  return num > 2;
});

REDUCE:

The reduce method reduces the array of values to just one value. It will execute the callback on each element of the array.

Code :

const nums = [1, 2, 3, 4];

const moreThanTwo = nums.reduce((acc, curr, i, arr) => {
  return acc + curr;
}, 0);

YT - @RoadSideCoder


WHAT IS ES6 AND ITS FEATURES

  • Es6 or ECMAScript 2015 is the 6th and major edition of the ECMAScript language specification standard. I defined the standarad for the implementation of JavaScript and it has become much more popular than the previous edition ES%

  • Es6 comes with significant changes to Javascript Language. It brought several new features like let and const keywords, spread and rest operators, template literals, classes , modules and many other enhancements to male JavaScript programming easier and more fun

Core Features of ES6

  • Let and const keywords
  • Arrow Functions
  • Multi Line Strings
  • Default Parameters
  • Template Literals
  • Destructing Assignment
  • Enhanced Object Literals
  • Promises
  • Classes
  • Modules

YT


DELETE OPERATOR


The delete operator removes a property from an object. If the property's value is an object and there are no more refereances to the object, the object held by that property is eventually released automatically. ### Code :

YT


SHALLOW COPY VS DEEP COPY


* Essentially all the avialable common methods for clonong an object or cloning aan array all create a shallow copy, they are work on refernces when it comes to nested arrays or nested objects. So if you have a nested obj / array , they will not work. Shallow copy is changes in instance of an object modifies the original object ( so if a = b change in b will bring change in a).
  • That's no good! To resolve the issue we need to write our own function of deep clone

Code :

const deepClone = (obj) => {
  if (typeof obj !== "object" || obj === null) return obj;

  // create an array / object to hold the values
  const newObject = Array.isArray(obj) ? [] : {};

  // loop through the object
  for (let key in obj) {
    const value = obj[key];

    // recursively (deep) copy for nested objects, including arrays
    newObject[key] = deepClone(value);
  }

  return newObject;
};

const oldScoreArray = [1, 2, 3, 4, 5];

const newScoreArray = deepClone(oldScoreArray);

newScoreArray[0] = 0;
console.log(newScoreArray);
console.log(oldScoreArray);
OUTPUT:
[ 0, 2, 3, 4, 5 ]
[ 1, 2, 3, 4, 5 ]

YT


YOUTUBE PLAYLIST: |

About

This repository contains interview questions for javascript

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published