Javascript Interview Prepration

What is Javascript

javascript is scripting or programming language that allow add to complex feature in web page such as dynamically updating content, controlling multimedia, animated images.

Data Types in Javascript

There are 2 kind of data type in js

1) Primitive

Number

String

Boolean

Undefined

Null

2) Object

in javascript except primitive data type everything object type

Array

Function

Object

Function

in javscript function encapsulate js code into reusable blocks

Types of function

Higher Order Function

it's the function which accept function as parameter and return a fuinction as result


const hocFn = (fn1) => {
    return fn1()
}

const fn1 = () => {
    console.log('hello saurabh')
}

hocFn(fn1)

First Class Function

The function which are treated as variable is called First Class Function

const fn = function() {
    console.log('this is first class function')
}

IIFE(Immediately Invoked Function Expression)

it's a function which is called as soon as it's defined

(()=> {
    console.log('This is IIFE)
})()

CallBack

It's a function which is passed as parameter to another function and excuted after and event or operation completed. it's widely used to handle asynchronous operation in js such as network request.

function fetchedData(cb) {
    setTimeout(() => {
        cb('sample call back data')
    }, 1000)
}

fetchedData((data) => {
    console.log(data)
})

Arrow Functions

it's shorter way of declaring function it has some other advantage as well

if there is only one expression it's implicitly return

const sum = () => a + b

It doesn't have own this context it get's it from parent scope where it's defined

Hoisiting

In javascript variable and function statement allocated memory before executing code this is called hoisting.

Functions gtes memory inside a heap and refrence available in execution context

Ex

real()
function real() {
    console.log('I am real always run me')
}
function real() {
    console.log('No I am real')
}
function real() {
    console.log('You both are wasted')
}
real();

// output
// You both are wasted
// You both are wasted

here all 3 will get meory in heap but real refres to last one so output will be "You both are wasted"

Lexical Scope

it's an ability of a function of accessing varaiable from it's parental scope

//lexical scope
// in js function variables are lexically scoped it means it can find outside the function defination
console.log('line no 1', varName); // undefined
var varName = 10;
function b() {
    console.log('at line no 10', varName);
}
function fn() {
    console.log('at line no 5', varName); // undefined
    var varName = 20;
    // suppose there is function where varName not defined
    b() // 10
    console.log('at line  no 7', varName) // 20
}
fn();

Closure

an inner function always have access of variable of outer functions even after executing outer function this concept is called closure

function outer() {
    let count = 0;

    function inner() {
        return count++
    }

    return inner;
}

const a = outer()
console.log(a())
console.log(a())
console.log(a())
console.log(a())

TDZ(Temporal Dead Zone)

unlike var keyword const and let can't access before declaration they have TDZ.

temporal dead zone is area from where js file starts and till where variable is decalred

console.log(a);
//TDZ
let a = 10

This Keyword in JS

This keyword in js is context refrence which depends on the scope and the manner how ithe function is called

1) Global Context

In Global Execution Context outside any function this refers to global object or window object

console.log(this)

2) Function Context

in strict mode it's undefined untill not set by call but for non strict mode it's global object

function show() {
    console.log(this)
    // strict mode undefined
    // non strict mode global object   
}

3) Arrow Functions

Arrow functions doesn't have there own this binding it inherit from the parent scope at the time of defining. it resolve the issue of explicit binding in react

function myFunction() {
  return () => {
    console.log(this);
  };
}

const obj = new myFunction();
obj();

Call, Bind, Apply

These are keywords which allow us assignment of this keyword and pass parameter to function in different ways

Call

it simply invoke the function after setting this value in call we pass parameters as list

function greet(greet) {
       console.log(`${greet} ${this.name}`)
}

const obj1 = {
    name: 'Saurabh'
}
const obj2 = {
    name: 'Rahul'
}
greet.call(obj1, 'hello')
greet.call(obj1, 'welcome')

Apply

it is simlar to call only difference is argument passed as Array

function greet(greet) {
       console.log(`${greet} ${this.name}`)
}

const obj1 = {
    name: 'Saurabh'
}
const obj2 = {
    name: 'Rahul'
}
greet.apply(obj1, ['hello'])
greet.apply(obj1, ['welcome'])

Bind

it return a function with specific this value which can be used later. so it's useful for event handling

function greet(greet) {
       console.log(`${greet} ${this.name}`)
}

const obj1 = {
    name: 'Saurabh'
}
const show = greet.bind(obj1);
show('welcome')

Polyfill

Polyfill is js piece of code that provide functionality which expected by natively supported browser

Polyfille for map

Array.prototype.myMap = function(cb) {
    let arr = [];
    for(let i = 0; i < this.length; i++) {    
        arr.push(cb(this[i], i, this))    
    }

    return arr
}

Polyfill for filter

Array.prototype.myFilter = function(cb) {
    let arr = []
    for(let i = 0; i < this.length; i++) {
        if(cb(this[i], i, this)) {
            arr.push(this[i])
        }
    }

    return arr
}

Polyfill for ForEach

Array.prototype.myForEach = function(callback){
   for (var i = 0; i < this.length; i++) {
      callback(this[i], i, this);
   }   
}

Polyfill for reduce

Array.prototype.myReduce = function(cb, initialValue) {
    let accumlatedValue = initialValue;
    for(let i = 0 ; i < this.length; i++) {
        if(!!accumlatedValue) {
            accumlatedValue = cb(this[i], accumlatedValue, i, this)
        }
        else {
            accumlatedValue = this[i]
        }
    }
    return accumlatedValue;
}

Prototype Inheritence

it's an js core concept which tells how objects and functions intract with each other.every object has prototype property whch is used for following

updating existing property

adding new property

inherting property of another object

after es6 js introduce class and extends keyword which is used for inheritence but internally it uses prototype

Promise

Promise are representation of eventual completion or failure of asynchronus operation and it's result value. before promise callback function is used which create call back hell for multiple asynchronus operation.

Promise has 3 state

Pending - it's initial State

Completed - when operation successfully completed

Rejected - When operation failed due to any reason

const p1 = new Promise((resolve, reject) => {
    if(false) {
        resolve(10)
    }
    else {
        reject('error')
    }
})

p1.then(data => {
    console.log(data)
})
.catch(error => {
    console.log(error)
})

Promise.all

when there are multiple promise which are not dependent on each other we want to execute something after completing all result we use promise.all it resolved if all promise success otherwise reject it.

const p1 = new Promise((resolve, reject) => {
    if(true) {
        resolve(10)
    }
    else {
        reject('error')
    }
})

const p2 = new Promise((resolve, reject) => {
    if(true) {
        resolve(20)
    }
    else {
        reject('error')
    }
})

Promise.all([p1, p2]).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})

Async / Await

it's used write and read asynchronus code in easy way

const p1 = new Promise((resolve, reject) => {
    if(true) {
        resolve(10)
    }
    else {
        reject('error')
    }
})

const p2 = new Promise((resolve, reject) => {
    if(true) {
        resolve(20)
    }
    else {
        reject('error')
    }
})

const displayPromiseResult = async () => {
    try {
        const allPromise = await Promise.all([p1, p2]);
        console.log(allPromise)
    }
    catch(error) {
        console.log(error)
    }
}

displayPromiseResult()

Let, Var and Const

var

Scope - The var keyword has functional and global scope.

redeclare - we can redeclare the variable by using the var keyword.

reassign - we can reassign values to the variable that are declared with the var keyword.

TDZ(Temporal Dead Zone) - There is no TDZ for the variable that is declared with the var keyword.

let

Scope - The let keyword has a block scope.

redeclare - we can't redeclare the variable by using the let keyword.

reassign - we can reassign values to the variables that are declared with the let keyword.

TDZ(Temporal Dead Zone) - TDZ is available for the variables declared with the let keyword.

const

it's used to declare constant values.

Scope - The const keyword has a block scope.

redeclare - we can't redeclare the variable by using the let keyword.

reassign - we can't reassign values to the variables that are declared with the const keyword.

SetTimeout vs SetInterval

setTimeout(function() {
    console.log("This message is shown after 3 seconds");
}, 3000);

it execute the code after specified delay

setInterval(function() {
    console.log("This message is shown every 2 seconds");
}, 2000);

it repeatedly execute same function in regular interval

Spread Operator

it's used to copy objects data

it's used concate objects

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const combinedObj = { ...obj1, ...obj2 }; // { a: 1, b: 3, c: 4 }

RestParameter

it's syntax similar to spread operator but it allow function expect indefinite arguments as an array

function sum(...numbers) {
  return numbers.reduce((acc, current) => acc + current, 0);
}

console.log(sum(1, 2, 3, 4)); // Outputs: 10

Shallow Copy

it just copy top level structure not nested objects

const obj = {
    name: 'saurabh'
    address: {
        add1: 'some address'
    }
}

const obj2 = {...obj}
const obj3 = Object.assign({}, obj)
// reference for address doesn't change

Deep Copy

it create new instance of the object or array by copying all the data but it has some limitation also it doesn't change reference for undefined, methods so for that we have structured clone for deep copy.

const obj = {
    name: 'saurabh'
    address: {
        add1: 'some address'
    }
}

const obj2 = JSON.parse(JSON.stringify(obj));

Event Delegation

it's a technique in which instead of adding event at each individual add events to there parent.

<ul id="myList">
   <li>First</li>
   <li>First</li>
   <li>First</li>
</ul>
document.getElementById('myList').addEventListener('click', function(event) {
    // Check if the clicked element is a list item
    if (event.target && event.target.nodeName === 'LI') {
        console.log('List item ', event.target.textContent, ' was clicked!');
    }
});

// This will work even for list items added later to the myList element

Event Propogation

It's a mechanism that tells how event propogate or travel through DOM(Document object model). It has 3 phases

1 Capturing - it goes from document object to target element

2 Target - trigger on target element

3 Bubbling - after reaching target element if bubbling is enabled it reverse back to top in dom tree till document object

Event Capturing

<div id="parentDiv">
  <div id="childDiv">Child Text</div>
</div>
document.getElementById('parentDiv').addEventListener('click',() => {
    alert('parent called',)
}, true)

document.getElementById('childDiv').addEventListener('click',() => {
    alert('child called',)
})

Event Bubbling

document.getElementById('parentDiv').addEventListener('click',() => {
    alert('parent called')
})

document.getElementById('childDiv').addEventListener('click',() => {
    alert('child called')
})

Throttling vs Debouncing

Throttling

it's a technique in which it doesn't matter how many times user fires a event it will excuted only once in a given time interval. loadsh library used for this

ex. used for scrolling

Debouncing

it's a technique in which attached callback is excuted after the specified time when user stops firing event.

ex. used for search data component

Object.seal vs Object.freeze

Object.seal()

When an object is sealed with Object.seal():

  1. Prevents Adding New Properties: You cannot add new properties to the sealed object.

  2. Prevents Deleting Existing Properties: You cannot remove existing properties from the sealed object.

  3. Allows Modification of Existing Properties: However, it still allows you to modify the values of existing properties (as long as they are writable).

const sealedObject = { prop: 1 };
Object.seal(sealedObject);

sealedObject.prop = 2; // Allowed
sealedObject.newProp = 3; // Not allowed, newProp will not be added
delete sealedObject.prop; // Not allowed, prop will not be deleted

Object.freeze()

Object.freeze() is more restrictive than Object.seal():

  1. Prevents Adding New Properties: You cannot add new properties to the frozen object.

  2. Prevents Deleting Existing Properties: You cannot remove existing properties.

  3. Prevents Modifying Existing Properties: It also prevents modifying the existing property values. This means that the object is made completely immutable (assuming its existing properties are primitive values or immutable themselves).

const frozenObject = { prop: 1 };
Object.freeze(frozenObject);

frozenObject.prop = 2; // Not allowed, prop will remain 1
frozenObject.newProp = 3; // Not allowed, newProp will not be added
delete frozenObject.prop; // Not allowed, prop will not be deleted

Set

// Creating a set
let mySet = new Set();

// Adding elements to the set
mySet.add(1);
mySet.add(2);
mySet.add(3);
mySet.add(2); // Duplicate entry, will be ignored

// Checking the size of the set
console.log(mySet.size); // Output: 3

// Checking if an element exists in the set
console.log(mySet.has(2)); // Output: true

// Deleting an element from the set
mySet.delete(2);

// Iterating over the set
mySet.forEach((value) => {
    console.log(value);
});

Map

A Map is a collection of key-value pairs where each key is unique. It's similar to an object but with more flexibility and additional methods for manipulation.

// Creating a map
let myMap = new Map();

// Adding key-value pairs to the map
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');
myMap.set('key3', 'value3');

// Getting the value associated with a key
console.log(myMap.get('key2')); // Output: value2

// Checking if a key exists in the map
console.log(myMap.has('key2')); // Output: true

// Deleting a key-value pair from the map
myMap.delete('key2');

// Iterating over the map
myMap.forEach((value, key) => {
    console.log(`${key} => ${value}`);
});

Generator Function

In JavaScript, a generator function is a special type of function that can be paused and resumed during its execution. It's defined using the function* syntax and yields values using the yield keyword. When a generator function is called, it returns a generator object, which can then be used to control the execution of the function

function* myGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

// Creating a generator object
const gen = myGenerator();

// Calling next() on the generator object returns an object with the value yielded by the generator
console.log(gen.next()); // Output: { value: 1, done: false }
console.log(gen.next()); // Output: { value: 2, done: false }
console.log(gen.next()); // Output: { value: 3, done: false }
console.log(gen.next()); // Output: { value: undefined, done: true }

Did you find this article valuable?

Support SAURABH TARAGI by becoming a sponsor. Any amount is appreciated!