javascript-code-challenges Documentation

A collection of JavaScript modern interview code challenges for beginners to experts

RAW Doc

File: README.md


Contributing Guide

If you want to contribute, improve or suggest changes to this repo, then check out the Contributing Guide

License

This repository is MIT licensed. Read more


File: CODE_OF_CONDUCT.md

Contributor Covenant Code of Conduct

Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

Our Standards

Examples of behavior that contributes to creating a positive environment
include:

  • Using welcoming and inclusive language
  • Being respectful of differing viewpoints and experiences
  • Gracefully accepting constructive criticism
  • Focusing on what is best for the community
  • Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

  • The use of sexualized language or imagery and unwelcome sexual attention or
    advances
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others' private information, such as a physical or electronic
    address, without explicit permission
  • Other conduct which could reasonably be considered inappropriate in a
    professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [email protected]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


File: contributing.md

Contribution Guide

  • Feel free to contribute to this repo by raising the pull request
  • Spelling mistakes, improvement of answers, code comments, rephrasing the questions/points, additional details, quality references, and similar contributions are highly appreciated

Question contribution

  • The question should be unambiguous and as generic as possible
  • Only JavaScript questions with coding solutions are allowed (No theoretical questions)
  • Any coding hints to be provided along with the question can be included as an example
  • This repo does not aim to solve algorithm questions in JavaScript
  • Answer can contain a maximum 4 parts
    • Important points related to solving the question or about the implementation logic - optional but recommended
    • Solution program (single or multiple solutions) - mandatory
    • Notes (additional detail about the answer) - optional
    • References - optional but recommended

Standards Followed

  • No full stop at the end of the question or points
  • Output of the code is mentioned in front of the statement with comments
  • Code comments should be before or after the code in a separate line
  • Driver codes are added only when necessary
  • The difficulty level of the question in general increases with the question number
  • Follow the existing format of markdown and code

Tech

  • Website is built using Nextra
  • The challenges are in mdx files
  • Add new questions to the end

File: usageGuide.md

Usage Guide

  • Familiarity and hands on experience in JavaScript are recommended before attempting these challenges
  • The JavaScript modern interview code challenges are divided into 5 sections topic wise
  • These sections are mutually exclusive for most of the questions and no ordering has to be followed for topics
  • Each section will have list of questions generally from easy to advanced level with increasing difficulty
  • All the questions are listed at the top of each section and clicking on the question will land to the answer section
  • Questions might have example which helps to understand the question better
  • Questions might have multiple solutions or answers divided in to multiple parts
  • Notes contain additional details about the solution
  • Try to solve the questions on your own before looking in to the solutions

Note

Do not use these challenges to learn JavaScript if you are new to JavaScript


File: web/README.md

Getting Started

First, run the development server:

bash
npm install
npm run dev
# or
yarn
yarn dev
# or
pnpm install
pnpm dev

Open http://localhost:3000 with your browser to see the result.

Tech stack

The project is built using Nextra


File: web/package.json

{
"name": "jscc",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"postbuild": "pagefind --site .next/server/app --output-path public/_pagefind"
},
"dependencies": {
"next": "^15.5.9",
"nextra": "^4.6.1",
"nextra-theme-docs": "^4.6.1",
"react": "^19.2.4",
"react-dom": "^19.2.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.5",
"@types/node": "^24.0.13",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"eslint": "^9.39.4",
"eslint-config-next": "^16.2.2",
"pagefind": "^1.4.0",
"typescript": "^5.8.3"
},
"overrides": {
"@xmldom/xmldom": "0.9.9"
}
}


File: web/tsconfig.json

{
"compilerOptions": {
"target": "ES2017",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/": [
"./src/
"
]
}
},
"include": [
"next-env.d.ts",
"/*.ts",
"
/.tsx",
".next/types/**/
.ts",
"next.config.mjs",
"src/mdx-components.js",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}


File: web/src/app/page.mdx

import Image from "next/image";
import { Cards } from "nextra/components";
import "./app.css";

export const metadata = {
title: "JavaScript Code Challenges",
}

Welcome to JS Code Challenges

Collection of modern interview code challenges on JavaScript suitable for
Interviewees | Interviewers | Knowledge test | Practice

Show your support by giving a ★ to JavaScript Code
Challenges
repo


File: web/src/app/challenges/async/page.mdx

export const metadata = {
title: "Async | Challenges",
}

1. Print "Hello, world" with a delay of 3 seconds

  • setTimeout takes a function as the 1st argument and optional timeout delay & list of values as the function parameters
  • setTimeout returns an id (number) which can be used to stop the setTimeout using clearTimeout function
js copy
setTimeout(
  function (text) {
    console.log(text);
  },
  3000,
  "Hello, World"
);
js copy
setTimeout(() => console.log("Hello, World"), 3000);
js copy
setTimeout(console.log, 3000, "Hello, World");

Notes

Zero or more values that represent any parameters you want to pass to the function when it is run.

References


2. Create a function which receives a function as argument and executes it after 2 seconds

js copy
function callbackExec(callback) {
  if (typeof callback === "function") {
    setTimeout(() => {
      callback();
      console.log("Callback is executed after 2 seconds");
    }, 2000);
  }
}

function displayHello() {
  console.log("Hello");
}

callbackExec(displayHello);

3. Print numbers from 1 to 10 with delay of 1 second between each value being printed

js copy
const num1 = 1,
  num2 = 10;
for (let i = num1; i <= num2; i++) {
  setTimeout(() => console.log(i), i * 1000);
}
js copy
const num1 = 1,
  num2 = 10;
(function displayWithDelay(i) {
  console.log(i);
  if (i !== num2) setTimeout(displayWithDelay, 1000, ++i);
})(1);

Notes

In the 2nd solution, recursive setTimeout is used.

References


4. Print numbers from 1 to 10 with delay of 1 second between each value being printed using setInterval

  • setInterval function repeats a block of code at every given timing event
  • clearInterval is used to stop the setInterval execution
js copy
const num1 = 1,
  num2 = 10;
let i = num1;
const intervalId = setInterval(() => {
  console.log(i++);
  if (i === num2 + 1) clearInterval(intervalId);
}, 1000);

5. Print numbers from 10 to 1 with delay of 1 second between each value being printed using setTimeout using pre ES6 features only

  • We can use 3rd parameter of setTimeout to pass the value of iteration which creates a new scope each time loop iterates
  • We can also use an inner function scope (IIFE) within the for loop for each iteration
js copy
var num1 = 10,
  num2 = 1;
for (var i = num1; i >= num2; i--) {
  setTimeout(console.log, (num1 - i) * 1000, i);
}
js copy
var num1 = 10,
  num2 = 1;
for (var i = num1; i >= num2; i--) {
  (function (i) {
    setTimeout(function () {
      console.log(i);
    }, (num1 - i) * 1000);
  })(i);
}

References


6. Write a utility which prints numbers starting from an initial value and increment in steps which can be started and stopped by the user, any number of times

  • The functionality to start and stop can be exposed from a function which internally takes care of incrementing and displaying data
  • setInterval can be used to achieve the task and handle the start & stop of data display
js copy
function timer(init = 0, step = 1) {
  var intervalId;
  var count = init;

  function startTimer() {
    if (!intervalId) {
      intervalId = setInterval(() => {
        console.log(count);
        count += step;
      }, 1000);
    }
  }

  function stopTimer() {
    clearInterval(intervalId);
    intervalId = null;
  }

  return {
    startTimer,
    stopTimer,
  };
}

// driver code
const timerObj = timer(100, 10);
timerObj.startTimer();
setTimeout(() => {
  timerObj.stopTimer();
}, 5000);

Notes

The function can also be modified to have completion after which timer can not be started


7. Execute an array of asynchronous functions one after the other in sequence using callbacks

  • The asynchronous function can be simulated using setTimeout which executes the callback
  • The array of functions execution can be managed by having a function which takes care of execution of all the async functions
  • Asynchronous functions need not be aware of the function to be executed and will take a callback as argument and execute it after completion
js copy
function asyncFunc1(callback) {
  console.log("Started asyncFunc1");
  setTimeout(() => {
    console.log("Completed asyncFunc1");
    callback();
  }, 3000);
}

function asyncFunc2(callback) {
  console.log("Started asyncFunc2");
  setTimeout(() => {
    console.log("Completed asyncFunc2");
    callback();
  }, 2000);
}

function asyncFunc3(callback) {
  console.log("Started asyncFunc3");
  setTimeout(() => {
    console.log("Completed asyncFunc3");
    callback();
  }, 1000);
}

function callbackManager(asyncFuncs) {
  function nextFuncExecutor() {
    const nextAsyncFunc = asyncFuncs.shift();
    if (nextAsyncFunc && typeof nextAsyncFunc === "function") {
      nextAsyncFunc(nextFuncExecutor);
    }
  }
  nextFuncExecutor();
}

// driver code
callbackManager([asyncFunc1, asyncFunc2, asyncFunc3]);

Notes

3 asynchronous functions are considered here, but the program should work for any number


8. Execute the given list of asynchronous functions in parallel and return the results as an array to the callback

js copy
// Example
function asyncFunc1(callback) {
  setTimeout(() => {
    callback(1);
  }, 3000);
}

function asyncFunc2(callback) {
  setTimeout(() => {
    callback(2);
  }, 2000);
}

function asyncFunc3(callback) {
  setTimeout(() => {
    callback(3);
  }, 1000);
}

asyncParallel([asyncFunc1, asyncFunc2, asyncFunc3], (result) => {
  console.log(result); // 1, 2, 3 (prints results of each asynchronous function in order)
});
  • The async functions can be executed in parallel using the loop and can be tracked for completion with a counter
  • The callback function can be sent to the async functions and the results will be stored in the array which will be returned after the completion of all
js copy
function asyncParallel(asyncFuncArr, callback) {
  const resultArr = new Array(asyncFuncArr.length);
  let resultCounter = 0;

  asyncFuncArr.forEach((asyncFn, index) => {
    asyncFn((value) => {
      resultArr[index] = value;
      resultCounter++;
      if (resultCounter >= asyncFuncArr.length) {
        callback(resultArr);
      }
    });
  });
}

References


9. Execute 3 asynchronous functions one after the other in sequence using promise chaining

  • The implementation of chaining is that the result is passed through the chain of then handlers for all the promises
  • then method on Promise also returns a promise which can be used to perform then on the returned promise
  • The errors in promise / promise chaining can be handled with the error callback for each promise when it settles or with a generic catch block
js copy
asyncFunc1().then(
  () => {
    console.log("Completed async1");
    asyncFunc2().then(
      () => {
        console.log("Completed async2");
        asyncFunc3().then(
          () => {
            console.log("Completed async3");
            console.log("All succeeded");
          },
          (err) => {
            console.log("Failure in " + err);
          }
        );
      },
      (err) => {
        console.log("Failure in " + err);
      }
    );
  },
  (err) => {
    console.log("Failure in " + err);
  }
);
js copy
asyncFunc1()
  .then(asyncFunc2)
  .then(asyncFunc3)
  .catch(() => {
    console.log("Error occurred in one of the async function");
  });

Notes

If then method has a return statement which is a promise then it will be considered for the next promise chain until it settles

References


10. Execute 3 asynchronous functions one after the other in sequence using async await

  • Async function with await for each promise can be used to execute in sequence
js copy
async function executor(){
    try {
        await asyncFunc1();
        await asyncFunc2();
        await asyncFunc3();
        console.log('All succeeded');
    } catch(){
        console.log("Error occured);
    }
}();

11. Execute 3 asynchronous functions one after the other in sequence using promise chaining and do not terminate on failure

  • The promise which gets rejected will invoke the 2nd function argument to then handler
  • The failure handler will receive the error and continue with next execution which will not propagate failures
js copy
async1()
  .then(
    () => {
      console.log("Async1 success");
    },
    () => {
      console.log("Async1 failure");
    }
  )
  .then(async2)
  .then(
    () => {
      console.log("Async2 success");
    },
    () => {
      console.log("Async2 failure");
    }
  )
  .then(async3)
  .then(
    () => {
      console.log("Async3 success");
    },
    () => {
      console.log("Async3 failure");
    }
  );

12. Execute 3 asynchronous functions one after the other in sequence using async await and do not terminate on failure

  • Unlike promises, try-catch block can be used on async functions
  • catch block for each asynchronous function can be used to catch errors and continue with next execution which will not propagate failures
js copy
(async function executor() {
  try {
    await asyncFunc1();
    console.log("Async1 success");
  } catch {
    console.log("Async1 failure");
  }
  try {
    await asyncFunc2();
    console.log("Async2 success");
  } catch {
    console.log("Async2 failure");
  }
  try {
    await asyncFunc3();
    console.log("Async3 success");
  } catch {
    console.log("Async3 failure");
  }
  console.log("All succeeded");
})();

13. Execute an array of asynchronous functions which returns a promise, one after the other in sequence

  • Asynchronous functions can be executed and promises can be captured in an array
  • Array method reduce can be used to make the sequential execution on promise settlement
js copy
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];

asyncFuncArr.reduce((acc, asyncFn) => {
  return acc.then(() => asyncFn().then(console.log));
}, Promise.resolve());
js copy
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];

asyncFuncArr.reduce(async (acc, asyncFn) => {
  await acc;
  console.log(await asyncFn());
}, Promise.resolve());

Notes

Promise.resolve() is used as the initial value to reduce, which resolves the promise immediately,


14. Execute an array of asynchronous functions simultaneously but print the output in the ordered sequence. Do not wait for printing the data if it already available after promise is settled

  • Array method reduce can be used to make the simultaneously execution on promise settlement
  • Unlike sequential execution, the parallel execution of asynchronous functions happen but the output will executed in order of sequence
js copy
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];

asyncFuncArr
  .map((async) => async())
  .reduce((acc, promise) => {
    return acc.then(() => promise).then((data) => console.log(data));
  }, Promise.resolve());
js copy
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];

asyncFuncArr
  .map((async) => async())
  .reduce(async (acc, promise) => {
    console.log(await acc.then(() => promise));
  }, Promise.resolve());

15. Design a utility which takes array of asynchronous functions and returns the 1st successful or non successful result with max waiting time set by the user

  • Promise.race is an in built JavaScript method which helps us to return the first resolved or rejected promise data from promises array
  • Timeout feature can be set by adding a function returning a promise which rejects after specified amount of time
  • If any promise resolves before timeout the promise which settles first will be the output else timeout will cause rejection
js copy
function timeoutFunc() {
    const delay = 500;
    return new Promise((resolve, reject) => {
        setTimeout(() => reject("Timeout"), delay));
    }
}

const asyncArr = [asyncFunc1, asyncFunc2, asyncFunc3, timeoutFunc];
const promiseArr = asyncArr.map(asyncFunc => asyncFunc());
Promise.race(promiseArr).then(console.log).catch(console.log);

16. Design a utility which takes URL and a value for attempts which will attempt to make a fetch request. If on failure it tries again with increasing delay for number of times which user has requested

  • Utility can designed which returns a promise which attempts to make requests and return the data on success
  • The fetch request attempts to make calls after increasing time delay on failure
  • If all the attempts by to get response fails, promise gets rejected
js copy
function requestManager(url, attempts = 3) {
  return new Promise(async (resolve, reject) => {
    for (let i = 0; i < attempts; i++) {
      try {
        const response = await fetch(url);
        resolve(response);
        break;
      } catch (err) {
        if (attempts - 1 === i) {
          reject(err);
          break;
        }
        await new Promise((resolve) => setTimeout(resolve, 1000 + 1000 * i));
      }
    }
  });
}

// driver code
requestManager("https://reqbin.com/echo/get/json", 3).then(
  (response) => console.log(response),
  (error) => console.log(error)
);

Notes

1000 + 1000 * i is used for delay after 1st unsuccessful attempt to fetch, which increases the delay on every iteration

References


17. Create a generator to return a random number on every request

  • The generation of random number can be implemented in the normal way in the function but will returned and function yields
  • The function will again continue to execute in loop to return a new random number
js copy
function* generatorFunc(param) {
  while (true) {
    yield Math.ceil(Math.random() * 100);
  }
}

// driver code
const it = generatorFunc();
const rand1 = it.next();
const rand2 = it.next();

Notes

Genertor function need not complete its execution

References


18. Search for the presence of a given value in the nested object using generator

  • With the help of generator Inversion of control is possible
  • Instead of function seaching for the key by passing the callback or key, the logic can be implemented in the controlling code
  • For..of loop calling the recursive generator function on object can be used to achieve this
js copy
function* objectReader(obj) {
  for (let key in obj) {
    if (typeof obj[key] === "object") {
      yield* objectReader(obj[key]);
    } else {
      yield obj[key];
    }
  }
}

// driver code
const it = objectReader({
  a: 1,
  b: 2,
  c: 3,
  d: { x: 4, y: 5, z: { m: 6, b: 7 } },
});
const searchValue = 5;

for (let value of it) {
  if (value === searchValue) {
    console.log(searchValue + " exists");
  }
}

File: web/src/app/challenges/collections/page.mdx

export const metadata = {
title: "Collections | Challenges",
}

1. Write a function which can concatenate 2 arrays. If only one array is passed it will duplicate it

  • Function can take 2 arguments which concatenates arrays
  • 2nd array parameter can be defaulted to 1st array if the value is not passed
js copy
function mergeArray(arr1, arr2 = arr1) {
  return [...arr1, ...arr2];
}
js copy
function mergeArray(arr1, arr2 = arr1) {
  return arr1.concat(...arr2);
}
js copy
function mergeArray(arr1, arr2 = arr1) {
  arr1.push(...arr2);
  return arr1;
}

Notes

When 2nd argument is not passed, the case is same as duplicating the array

References


2. Write a program to replace 3 center elements of the 1st array by center 3 elements of the 2nd array

  • slice method on array can be used to fetch the values of range in the array
  • splice method on array can be used to replace the value of range in the array
js copy
const a = [1, 2, 3, 4, 5];
const b = [4, 0, 0, 0, 8];

const startPositionFor1stArray = a.length / 2 - 1;
const startPositionFor2ndArray = b.length / 2 - 1;
a.splice(
  startPositionFor1stArray,
  3,
  ...b.slice(startPositionFor2ndArray, startPositionFor2ndArray + 3)
);

Notes

The center most 3 values of array 'a' is replaced by 'b'


3. Sort the given array of integers in ascending or descending order

  • sort method sorts the elements of an array in place and returns the sorted array
  • It receives a function as an argument, which is used for comparision
js copy
arr.sort((a, b) => a - b); // ascending
arr.sort((a, b) => b - a); // descending

Notes

If function is not passed an argument, default sorting will happen

References


4. Sort the given array of objects in ascending order according the authors lastname

js copy
// Example
const books = [
  { name: "Harry Potter", author: "Joanne Rowling" },
  { name: "Warcross", author: "Marie Lu" },
  { name: "The Hunger Games", author: "Suzanne Collins" },
];
  • sort takes a function and expects the return value to be an integer for sorting
  • The last names of the author can be compared and the result can be returned for sorting
js copy
books.sort((book1, book2) => {
  const authorLastName1 = book1.author.split(" ")[1];
  const authorLastName2 = book2.author.split(" ")[1];
  return authorLastName2 > authorLastName1 ? -1 : 1;
});

Notes

Returning a true or false will not work as the algorithm expects an integer value


5. Square all the positive numbers of the array and return the output array

  • filter is the method on Array which can be used to filter. It receives a function which can return boolean to filter the elements
  • map is the method on Array which can be used to map the values to new values. It receives a function which can return the modified value
js copy
const positiveArr = arr.filter((value) => value >= 0);
const squaredPositiveArr = arr.map((value) => value * value);
js copy
const squaredPositiveArr = arr
  .filter((value) => value >= 0)
  .map((value) => value * value);

Notes

2nd solution uses method chaining where the return value from filter fuction is an array on which map method is being called

References


6. Write a code to generate an array with range of numbers and shuffle them

  • An array of numbers in the range can be generated from a function which can take start and end value of the range
  • The shuffling can be achieved simply by sorting the array using a function which randomly returns positive or negative numbers
  • The shuffling of the values can be also done by picking a value from a random index from the current array and moving it in to a new array
js copy
function rangeGenFunc(start = 1, end = 0) {
  const arr = [];
  for (let i = start; i <= end; i++) {
    arr.push(i);
  }
  return arr;
}

const arr = rangeGenFunc(1, 10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
arr.sort(() => 0.5 - Math.random()); // [6, 8, 5, 10, 4, 3, 9, 2, 7, 1]
js copy
function* rangeGen(start = 1, end = 0) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}

let arr = [...rangeGen(1, 10)]; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let shuffledArr = [];
const length = arr.length;
for (let i = 0; i < length; i++) {
  shuffledArr.push(...arr.splice(Math.floor(Math.random() * arr.length), 1));
}

console.log(shuffledArr); // [5, 4, 7, 10, 3, 6, 8, 2, 1, 9]

Notes

2nd solution uses generator function to generate the range of values which can be converted to an array by spreading.


7. Check if the user with the name "John" exists in the array of objects

js copy
const doesJohnExist = arr.some((obj) => obj.name === "John");
js copy
const jonhObject = arr.find((obj) => obj.name === "John");
const doesJohnExist = jonhObject ? true : false;
js copy
const jonhIndex = arr.findIndex((obj) => obj.name === "John");
const doesJohnExist = jonhIndex < 0 ? false : true;

8. Generate an array of objects with properties id and full name from an array of objects where each object will have id, firstname and lastname

  • To manipulate array of objects map method can be used
js copy
const employeesListWithFullName = arr.map((obj) => {
  return { id, fullName: obj.firstName + " " + obj.lastName };
});

9. Write a program to calculate the sum of all the values of an array

  • Sum of the values of an array can calculated by iterating and adding all the values of the array
  • reduce method of array can be used efficiently to calculate the sum with or without initial value
js copy
const sum = arr.reduce((acc, value) => acc + value, 0);
js copy
const sum = arr.reduce((acc, value) => acc + value);
js copy
const sum = 0;
for (let value of arr) {
  sum = sum + value;
}

Notes

reduce method takes a function as 1st argument and initial value as 2nd argument. The return value of current iteration will be 1st argument for the next iteration along with the next element of the array

References


10. Get the maximum value from a numbers array along with its index

  • Math.max is a method which returns maximum value from a given list of values
  • reduce can also be designed to return the maximum value of each comparision
js copy
const max = Math.max(...arr);
arr.indexOf(max); // position of max number
js copy
let max = a[0],
  position = 0;
for (let index in arr) {
  if (arr[index] > max) {
    position = index;
    max = value;
  }
}

position; // position of max number
js copy
const max = arr.reduce((a, b) => (a > b ? a : b));
arr.indexOf(max); // position of max number

Notes

Though 1st solution is verbose compared to 2nd, but has good performance

References


11. Find the number of occurences of minimum value in the numbers list

  • filter method can be used to fetch all the minimum values and we can get the count of those values
js copy
const min = Math.min(...arr);
minArr = arr.filter((value) => value === min);
minArr.length; // count of minimum value occurences

12. Create an array of length n with all the values of it set to 10

  • fill is a method on Array prototype which fills all the slots of array with the value given passed as the argument
js copy
const n = 5;
const arr = new Array(n);
arr.fill(10);

Notes

If an object is passed the object reference is copied to all the slots and not the different objects

References


13. Write the code to remove the duplicates from the array

  • Set is a data structure which does not allow duplicate elements
js copy
const set = new Set(arr);
const distinctArr = [...set];

14. Design a flat function which flattens an array to any depth

  • Flat function can be used to flatten the array by recursive call
js copy
function flat(arr) {
  const flatArr = [];
  arr.forEach((value) => {
    if (Array.isArray(value)) {
      flatArr.push(...flat(value));
    } else {
      flatArr.push(value);
    }
  });
  return flatArr;
}

15. Check if all the students of have passed or not (40 is the pass marks)

  • every is a method on Array prototype which returns true only if all the elements condition satisfies the condition
js copy
const isAllPass = students.every((student) => student.marks >= 40);

16. Get the average of all the salaries which is greater than 10000 from the department of "IT" from the array of objects)

js copy
const itEmployeesWithSalaryGT10K = employees.filter(
  (employee) => employee.salary > 10000 && employee.dept === "IT"
);
const itTotalSalaryGT10K = itEmployeesWithSalaryGT10K.reduce(
  (acc, value) => acc + value,
  0
);
const itAvgSalaryGT10K = itTotalSalaryGT10K / itEmployeesWithSalaryGT10K.length;

17. Extract the list of all the elements from the list of numbers given in 2 arrays

  • The union array will be the result if all the elements from the 2 arrays are picked
js copy
const set1 = new Set(arr1);
const set2 = new Set(arr2);
const distinctArr = [...set1, ...set2];

18. Get the list of all distinct elements which are present in both list of numbers

  • The intersection array will be the result if the common elements from the 2 arrays are picked
js copy
const intersectionArr = arr1.filter((value) => arr2.includes(value));
const distinctIntersectionArr = [...new Set(intersectionArr)];
js copy
const set1 = new Set(arr1);
const set2 = new Set(arr2);
const distinctIntersectionArr = [...set1].filter((value) => set2.has(value));

19. Extract list of elements present only in the first list given.

  • The only present elements of 1st list will be the result when all the elements of 1st list not present in the 2nd are chosen
js copy
const set1 = new Set(arr1);
const set2 = new Set(arr2);
const intersectionArr = [...set1].filter((value) => !set2.has(value));

Notes

Elements of 2nd list only can be obtained by checking for all the elements of lis 2 which are not present in list1


20. Create a function named "average" which can calculate the average of an array and should be available to be called from any Array object.

  • The function added to Array prototype are accessible to all the objects of Array
js copy
Array.prototype.average = function () {
  let total = 0;

  for (let index in this) {
    total += this[index];
  }
  return total / this.length;
};

21. Write a code to eliminate duplicate objects in an array where each object has an 'id' property which can be used to identify the object and the duplicate object with lower rank to be removed

js copy
// Example
const arr = [
  {
    id: 1,
    name: "emp1",
    rank: 4,
  },
  {
    id: 2,
    name: "emp2",
    rank: 1,
  },
  {
    id: 2,
    name: "emp2",
    rank: 2, // this is a duplicate object (id = 2) and has lower rank
  },
  {
    id: 3,
    name: "emp3",
    rank: 3,
  },
];
  • The duplicate objects cannot be removed using Set as the 2 objects with same structure and data have different references
  • Map can be used to have 'id' as the key and object as value
  • If 'id' is already present in the array, object with the higher rank can be retained
js copy
const map = new Map();

arr.forEach((obj) => {
  if (map.has(obj.id)) {
    if (obj.rank < map.get(obj.id).rank) {
      map.set(obj.id, obj);
    }
  } else {
    map.set(obj.id, obj);
  }
});

distinctArr = [...map.values()];

22. Create an array which will only accept string values. (Homogeneous array of strings)

  • Array in JavaScript a collection of values of any type by default
  • Proxy can be used to validate and insert to the array only if the value satisfies the condition using set trap
js copy
var stringsArr = [];

var stringsArr = new Proxy(stringsArr, {
  set(target, prop, receiver) {
    if (typeof receiver === "string") {
      target[target.length] = receiver;
    }
    return true;
  },
});

// driver code
stringsArr.push("Hello", 5, {}, "world", true, [1, 2, 3]);
stringsArr; // ["Hello", "world"]

Notes

The functionality of the code can be modified to make the array accept any one or more kind of values only


23. Create a Proxy object through which the array can be accessed as usual but also allow to access the values through negative indices

js copy
// Example
let arr = [10, 20, 30];

arr[-1]; // 30
arr[-2]; // 20
  • get trap of proxy can be used to map the negative index to the valid array position
js copy
arr = new Proxy(arr, {
  get(target, handler) {
    if (handler < 0) return target[target.length + Number(handler)];
    else return target[handler];
  },
});

File: web/src/app/challenges/dom/page.mdx

export const metadata = {
title: "DOM | Challenges",
}

1. Show the different ways of selecting an element from DOM

  • The element can be selected using its tagname, id, attribute, value etc
js copy
document.getElementById("elementId"); // elementId is id of the element
document.querySelector(".my-class"); // element having a class 'my-class'

Notes

Above selectors are used to select a first matching element reference even if multiple matches be there

References


2. Show the ways to loop over the Nodelist obtained after querying for the elements

  • The Nodelist can be obtained by queryng for multiple elements
  • As list of elements are array like object (not pure JS array), all the array methods can't be directly used
js copy
// Lets assume DOM elements are fetched in the variable domElements
for (let element of domElements) {
  // perform operation on element
}

References


3. Design and Implement a Node Store, which supports DOM element as key

  • Implement it without using inbuilt Map
  • Can you do it in O(1) Time complexity?
js copy
class NodeStore {
  constructor() {
    this.store = {};
  }
  /**
   * @param {Node} node
   * @param {any} value
   */
  set(node, value) {
    node.__nodeIdentifier__ = Symbol();
    this.store[node.__nodeIdentifier__] = value;
  }
  /**
   * @param {Node} node
   * @return {any}
   */
  get(node) {
    return this.store[node.__nodeIdentifier__];
  }

  /**
   * @param {Node} node
   * @return {Boolean}
   */
  has(node) {
    return !!this.store[node.__nodeIdentifier__];
  }
}

References


4. Implement a function to find the closest ancestor with the provided selector (Element.closest() method)

  • The closest() method traverses the Element and its parents (heading toward the document root) until it finds a node that matches the provided selector string. Will return itself or the matching ancestor. If no such element exists, it returns null.
js copy
Element.prototype.closest = function (selector) {
  var el = this;
  while (el) {
    if (el.matches(selector)) {
      return el;
    }
    el = el.parentElement;
  }
  return null;
};

References


5. Write a function to find the corresponding node in two identical DOM trees

  • Given two same DOM tree A, B, and an Element a in A, find the corresponding Element b in B. By corresponding, we mean a and b have the same relative position to their DOM tree root.
js copy
const A = document.createElement("div");
A.innerHTML = `
<div>
<div>
  <div>
    <div id="node1"></div>
  </div>
  <div>
  </div>
  <div>
    <div>
      <p id="node2"></p>
    </div>
  </div>
<div>
</div>`;

const B = A.cloneNode(true);
const node1 = A.querySelector("#node1");
const node2 = A.querySelector("#node2");
const node1Target = B.querySelector("#node1");
const node2Target = B.querySelector("#node2");

findCorrespondingNode(A, B, node1); // node1Target
findCorrespondingNode(A, B, node2); // node2Target
js copy
const findCorrespondingNode = (rootA, rootB, target) => {
  if (rootA === target) return rootB;

  if (rootA.childElementCount) {
    for (let i = 0; i < rootA.childElementCount; i++) {
      let result = findCorrespondingNode(
        rootA.children[i],
        rootB.children[i],
        target
      );
      if (result) {
        return result;
      }
    }
  }
};

References


6. Write a function to get depth of a given DOM tree

  • A depth of a given DOM tree is the max depth till which DOM nodes are nested
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {number}
 */
function getHeight(root) {
  if (!root) return 0;

  let maxDepth = 0;

  const helper = (current, depth = 1) => {
    if (current.hasChildNodes()) {
      for (let child of current.children) {
        helper(child, depth + 1);
      }
    }
    maxDepth = Math.max(maxDepth, depth);
  };

  helper(root);
  return maxDepth;
}

7. Implement a function to get the root node of a given DOM fragment (document.getRootNode() method)

  • Root node is the topmost parent node of any given DOM fragment
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {HTMLElement | null}
 */
function getRootNode(tree) {
  if (!tree) return null;

  while (tree.parentElement) {
    tree = tree.parentElement;
  }

  return tree;
}

References


8. Implement a function to get unique tag names in a given DOM tree

js copy
/**
 * @param {HTMLElement | null} tree
 * @return {Array}
 */
function getUniqueTags(root, result = new Set()) {
  if (!root) return [];

  if (!result.has(root.tagName)) {
    result.add(root.tagName);
  }

  if (root.hasChildNodes()) {
    for (let child of root.children) {
      getUniqueTags(child, result);
    }
  }

  return [...result];
}

References


9. Implement a function to get elements by tag name (document.getElementsByTagName() method)

  • The getElementsByTagName method of Document interface returns an HTMLCollection of elements with the given tag name.
  • For example, document.getElementsByTagName('div') returns a collection of all div elements in the document.
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {Array}
 */
function getElementsByTagName(root, tagName) {
  if (!root) return [];

  let result = [];

  if (root.tagName.toLowerCase() === tagName.toLowerCase()) {
    result.push(root);
  }

  if (root.hasChildNodes()) {
    for (let child of root.children) {
      result = result.concat(getElementsByTagName(child, tagName));
    }
  }

  return result;
}

References


10. Implement a function to check if a given DOM tree has duplicate IDs

  • In a given DOM tree, the id on each node has be unique
  • Although HTML is very forgiving, but we should avoid duplicate identifiers
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {Boolean}
 */
function hasDuplicateId(tree, idSet = new Set()) {
  if (!tree) return false;

  if (idSet.has(tree.id)) return true;

  tree.id && idSet.add(tree.id);

  if (tree.hasChildNodes()) {
    for (let child of tree.children) {
      const result = hasDuplicateId(child, idSet);
      if (result) return true;
    }
  }

  return false;
}

11. Implement a function to get all descendants of a given DOM node

  • This function retrieves all child elements, regardless of depth.
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {Array}
 */
function getAllDescendants(root) {
  if (!root) return [];

  let descendants = [];

  const helper = (node) => {
    if (node) {
      descendants.push(node);
      if (node.children.length) {
        for (let child of node.children) {
          helper(child);
        }
      }
    }
  };

  helper(root);
  return descendants;
}

References


12. Implement a function to clone a DOM tree

  • This function creates a deep copy of the given DOM node and its descendants.
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {HTMLElement | null}
 */
function cloneDOMTree(root) {
  return root ? root.cloneNode(true) : null;
}

References


13. Implement a function to count all elements in a DOM tree

  • This function counts all child elements, regardless of depth.
js copy
/**
 * Counts all child elements in a DOM tree.
 *
 * @param {HTMLElement | null} root - The root element from which to start counting.
 * @return {number} - The total number of child elements.
 */
function countElements(root) {
  if (!root) return 0;

  let count = 1; 

  for (let child of root.children) {
    count += countElements(child);
  }
  return count;
}

14. Implement a function to serialize a DOM tree into a string

  • This function converts a DOM tree into a string representation.
js copy
/**
 * @param {HTMLElement | null} tree
 * @return {string}
 */
function serializeDOM(root) {
  if (!root) return '';

  let str = `<${root.tagName.toLowerCase()}`;

  for (let attr of root.attributes) {
    str += ` ${attr.name}="${attr.value}"`;
  }

  str += '>';

  if (root.hasChildNodes()) {
    for (let child of root.children) {
      str += serializeDOM(child);
    }
  }

  str += `</${root.tagName.toLowerCase()}>`;
  return str;
}

References


15. What is event delegation in the DOM and how can it be implemented in JavaScript?

  • Event delegation allows you to attach a single event listener to a parent element to manage events from its child elements, leveraging event bubbling. This improves performance and simplifies handling dynamically added elements.

Here’s an example of how event delegation works:

js copy
document.querySelector('#parent').addEventListener('click', function(event) {
  if (event.target && event.target.matches('button')) {
    console.log('Button clicked:', event.target.textContent);
  }
});

This approach optimizes performance and reduces memory usage, as fewer event listeners are attached to individual elements.

References


16. How can you find all leaf nodes in a given DOM tree?

  • Leaf nodes in a DOM tree are elements that do not have any child elements. You can traverse the tree recursively to collect all leaf nodes.

Implementation:

js copy
function getLeafNodes(element) {
  let leafNodes = [];

  // Base case: if the element has no children, it's a leaf node
  if (!element.children || element.children.length === 0) {
    leafNodes.push(element);
    return leafNodes;
  }

  // Recursive case: traverse through each child
  for (let i = 0; i < element.children.length; i++) {
    leafNodes = leafNodes.concat(getLeafNodes(element.children[i]));
  }

  return leafNodes;
}

// Example usage:
const leafNodes = getLeafNodes(document.body);
console.log('Leaf nodes:', leafNodes);

In this implementation:

The function checks if the current element has no children. If so, it adds it to the leafNodes array.
Otherwise, it recursively collects leaf nodes from each child.

References



File: web/src/app/challenges/event/page.mdx

export const metadata = {
title: "Event | Challenges",
}

1. Handling a Click Event to Change Text Content

  • In JavaScript, you can add event listeners to elements to respond to various events like mouse clicks, keyboard input, etc.
  • The addEventListener method is used to attach an event handler to an HTML element.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Click Event Example</title>
</head>
<body>
    <button id="myButton">Click me</button>
    <p id="myText">Original Text</p>

    <script>
        const button = document.getElementById('myButton');
        const text = document.getElementById('myText');

        button.addEventListener('click', () => {
            text.textContent = 'Text Changed!';
        });
    </script>
</body>
</html>

When the button is clicked, the text content of the paragraph is changed.

References

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener


2. Mouse Hover Event to Change Background Color

  • The mouseover and mouseout events can be used to change the background color of an element when the mouse is hovered over it.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mouse Hover Example</title>
</head>
<body>
    <div id="hoverDiv" style="width: 200px; height: 100px; background-color: lightgrey;">
        Hover over me!
    </div>

    <script>
        const div = document.getElementById('hoverDiv');

        div.addEventListener('mouseover', () => {
            div.style.backgroundColor = 'lightblue';
        });

        div.addEventListener('mouseout', () => {
            div.style.backgroundColor = 'lightgrey';
        });
    </script>
</body>
</html>

When the mouse pointer enters the element, the background color changes to light blue, and when it leaves, it reverts to light grey.

References

https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent


3. Form Submission Event to Prevent Default Behavior

  • The submit event can be used to intercept form submissions, and you can prevent the default behavior using event.preventDefault().
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Form Submission Example</title>
</head>
<body>
    <form id="myForm">
        <input type="text" placeholder="Enter text" required />
        <button type="submit">Submit</button>
    </form>

    <script>
        const form = document.getElementById('myForm');

        form.addEventListener('submit', (event) => {
            event.preventDefault();
            alert('Form submission intercepted!');
        });
    </script>
</body>
</html>

The form submission is prevented, and an alert is displayed instead.

References

https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault


4. Keyboard Event to Detect Key Presses

  • The keydown and keyup events can be used to detect when a key is pressed or released.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Keyboard Event Example</title>
</head>
<body>
    <input type="text" id="inputField" placeholder="Type something..." />

    <script>
        const inputField = document.getElementById('inputField');

        inputField.addEventListener('keydown', (event) => {
            console.log('Key pressed:', event.key);
        });
    </script>
</body>
</html>

When you type in the input field, the key pressed is logged to the console.

References

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent


5. Event Delegation to Handle Events on Multiple Elements

  • Event delegation is a technique of using a single event listener to manage events for multiple child elements.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Event Delegation Example</title>
</head>
<body>
    <ul id="itemList">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>

    <script>
        const itemList = document.getElementById('itemList');

        itemList.addEventListener('click', (event) => {
            if (event.target && event.target.nodeName === 'LI') {
                console.log('Clicked item:', event.target.textContent);
            }
        });
    </script>
</body>
</html>

Clicking on any list item triggers the event listener, logging the item's text.

References

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation


6. Double Click Event to Toggle Element Visibility

  • The dblclick event is used to handle double-click actions.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Double Click Event Example</title>
</head>
<body>
    <p id="toggleText">Double-click to hide/show this text.</p>

    <script>
        const text = document.getElementById('toggleText');

        text.addEventListener('dblclick', () => {
            text.style.display = text.style.display === 'none' ? 'block' : 'none';
        });
    </script>
</body>
</html>

Double-clicking the paragraph toggles its visibility.

References

https://developer.mozilla.org/en-US/docs/Web/API/Element/dblclick_event


7. Triggering a Custom Event

  • You can create and trigger custom events using the CustomEvent constructor.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Custom Event Example</title>
</head>
<body>
    <button id="triggerButton">Trigger Custom Event</button>

    <script>
        const button = document.getElementById('triggerButton');

        button.addEventListener('myCustomEvent', (event) => {
            console.log('Custom event triggered:', event.detail);
        });

        button.addEventListener('click', () => {
            const customEvent = new CustomEvent('myCustomEvent', { detail: 'Some custom data' });
            button.dispatchEvent(customEvent);
        });
    </script>
</body>
</html>

Clicking the button triggers a custom event, and the custom data is logged.

References

https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent


8. Debouncing an Input Event to Improve Performance

  • Debouncing limits the rate at which a function is executed.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Debouncing Example</title>
</head>
<body>
    <input type="text" id="debounceInput" placeholder="Type something..." />

    <script>
        const input = document.getElementById('debounceInput');

        let debounceTimeout;
        input.addEventListener('input', () => {
            clearTimeout(debounceTimeout);
            debounceTimeout = setTimeout(() => {
                console.log('Debounced input:', input.value);
            }, 300);
        });
    </script>
</body>
</html>

The function is only executed after the user stops typing for 300 milliseconds.

References


9. Using the once Option in Event Listener

The once option lets an event listener execute only once, after which it automatically removes itself.

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Once Event Listener Example</title>
</head>
<body>
    <button id="oneClickButton">Click me only once</button>

    <script>
        const button = document.getElementById('oneClickButton');

        button.addEventListener('click', () => {
            alert('Button clicked once!');
        }, { once: true });
    </script>
</body>
</html>

References


10. Handling focus and blur Events for Input Validation

The focus and blur events are helpful for form validation, showing messages when an input gains or loses focus.

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Focus and Blur Example</title>
</head>
<body>
    <input type="text" id="username" placeholder="Enter username" />
    <p id="message" style="display: none; color: red;">Username is required!</p>

    <script>
        const input = document.getElementById('username');
        const message = document.getElementById('message');

        input.addEventListener('focus', () => {
            message.style.display = 'none';
        });

        input.addEventListener('blur', () => {
            if (!input.value) {
                message.style.display = 'block';
            }
        });
    </script>
</body>
</html>

References


11. Preventing Event Propagation

Sometimes, you might want to prevent an event from propagating to parent elements using stopPropagation.

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Stop Propagation Example</title>
</head>
<body>
    <div id="outer" style="padding: 20px; background-color: lightcoral;">
        Outer Div
        <div id="inner" style="padding: 20px; background-color: lightblue;">
            Inner Div
        </div>
    </div>

    <script>
        const outer = document.getElementById('outer');
        const inner = document.getElementById('inner');

        outer.addEventListener('click', () => {
            alert('Outer div clicked');
        });

        inner.addEventListener('click', (event) => {
            alert('Inner div clicked');
            event.stopPropagation();  // Prevents the outer div click from triggering
        });
    </script>
</body>
</html>

References



File: web/src/app/challenges/functions/page.mdx

export const metadata = {
title: "Functions | Challenges",
}

1. Design a Calculator interface for 2 number inputs which can perform sum, difference, product and dividend whenever invoked on the same interface

js copy
// Example
const calc12And5 = Calculator(12, 5);
calc12And5.sum(); // 17
calc12And5.difference(); // 7
calc12And5.product(); // 60
calc12And5.dividend(); // 2
  • Simple revealing module pattern can be used which receives inputs and executes different operations exposed through functions
js copy
function Calulator(num1, num2) {
  function sum() {
    return num1 + num2;
  }

  function difference() {
    return num1 - num2;
  }

  function product() {
    return num1 * num2;
  }

  function dividend() {
    return Math.floor(num1 / num2);
  }

  return { sum, difference, product, dividend };
}

Notes

The solution provided is one of the way to achieve the interface. The design and solution can vary

References


2. Design a private counter function which exposes increment and retrive functionalities

js copy
function privateCounter(){
    var count = 0;
    return {
        increment: function(val = 1){
            count += val;
        }
        retrieve: function(){
            return count;
        }
    }
}

// driver code
const counter = privateCounter();
counter.increment();
counter.increment();
counter.retrieve();             // 2
counter.increment(5);
counter.increment();
counter.retrieve();             // 8

Notes

'increment' function takes an argument to increment if passed else which is set to 1 (increments by 1)

References


3. Write a polyfill for bind function

  • The bind method creates a new function that, when called, has its this keyword set to the provided context
js copy
if (!Function.prototype.bind) {
  Function.prototype.bind = function (context) {
    var fn = this;
    var fnArgs = Array.prototype.slice.call(arguments, 1);

    return function () {
      var allArgs = fnArgs.concat(Array.prototype.slice.call(arguments));
      fn.apply(context, allArgs);
    };
  };
}

Notes

This is a simple polyfill for bind without handling corner cases. It does not work when using the new operator

References


4. Write a function which will create a function bounded to the context like `bind`, but can be overridden when the context is set explicitly

  • The functionality is similar to bind with exception that if there is a context set during the execution it will override
js copy
function softBind(fn, context) {
  var fnArgs = Array.prototype.slice.call(arguments, 2);

  return function () {
    var allArgs = fnArgs.concat(Array.prototype.slice.call(arguments));

    // override the context to incoming context if it is not undefined, null or window
    var finalContext = !this || this === window ? context : this;
    fn.apply(finalContext, allArgs);
  };
}

Notes

This functionality is also known as 'Soft Binding'

References


5. Write a function which helps to achieve multiply(a)(b) and returns product of a and b

js copy
// Example
multiply(2)(4); // 8
multiply(5)(3); // 15
  • The implementation of this can be achieved by calling a function which returns a function
js copy
function multiply(num1) {
  return function (num2) {
    return num1 * num2;
  };
}

References


6. Create a function which takes another function as an argument and makes it eligible for currying or partial application

  • Function can take another function as argument and accept the arguments on the returned functions till the expected arguments are reached
  • The arguments can be 1 or multiple, and the actual function will be called once the count of expected arguments are reached
js copy
function curryFunc(fn) {
    return function curry(...args) {
        if(args.length < fn.length) {
            return curry.bind(this, ...args);
        }
        return fn.apply(this, args);
    }
}

// driver code
let sum = curryFunc(function (a, b, c, d) {
  return a + b + c + d;
});

sum(1)(2)(3)(4); // called like curried function
sum(1, 2)(3, 4); // called like partial application

References


7. Design a function which helps to do debouncing

  • The debounce function forces a function to wait a certain amount of time before running again
  • The function is built to limit the number of function calls to improve the performance
  • Debounce function design can take function (to be debounced), delay and the optional context
js copy
function debounce(fn, delay, context) {
  let timer;

  return function (...args) {
    if (timer) clearTimeout(timer);

    context = this ?? context;
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
}

Notes

Context is replaced while debounce function call in presence of a context. If not, context set during the debounce function call is used.

References


8. Design a function which helps to do throttling

  • The throttling function forces a function to run once in an amount of time for one or multiple calls
  • The function is built to limit the number of function calls to improve the performance
  • Throttling function design can take function (to be throttled), delay and the optional context
js copy
function throttle(fn, delay, context) {
  let timer;
  let lastArgs;

  return function (...args) {
    lastArgs = args;
    context = this ?? context;

    if (timer) return;

    timer = setTimeout(() => {
      fn.apply(context, lastArgs);
      clearTimeout(timer);
    }, delay);
  };
}

Notes

Last arguments to the throttled function is saved so that most recent arguments will be used for throttled function execution (unlike debouncing where it is taken care due to its way of execution)

References


9. Design an interface which limits the number of function calls by executing the function once for a given count of calls

  • function forces a function run to for specific number of times in a given number of execution calls
  • The function is built to limit the number of times a function is called
  • Throttling function design can take function (to be throttled), delay and the optional context
js copy
function sampler(fn, count, context) {
  let counter = 0;

  return function (...args) {
    lastArgs = args;
    context = this ?? context;

    if (++counter !== count) return;

    fn.apply(context, args);
    counter = 0;
  };
}

Notes

Sampling is different from throttling in the way that sampling limits the execution by executing function once in a given number of calls where as throttling limits the execution by executing function once in a given amount of time

References


10. Write a singleton function to create an object only once

  • Singleton is a design pattern which restricts the creation of only one object from a given interface
  • When requested multiple times, same object is returned
js copy
var Singleton = (function () {
  var instance;

  function createInstance() {
    var object = new Object("I am the instance");
    return object;
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    },
  };
})();

// driver code
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

Notes

Here both 'instance1' and 'instace2' are referencing to the same object

References


11. Design a function with toggle functionality for given list of inputs where toggle function accepts list of values to be toggled upon

js copy
// Example
var hello = toggle("hello");
var onOff = toggle("on", "off");
var speed = toggle("slow", "medium", "fast");

hello(); // "hello"
hello(); // "hello"

onOff(); // "on"
onOff(); // "off"
onOff(); // "on"

speed(); // "slow"
speed(); // "medium"
speed(); // "fast"
speed(); // "slow"
  • Toggle functionality can be obtained by returning the next value cyclically on each call to the function
  • The toggle function will return another function which maintains the closure over the values with which it was initialized
js copy
function toggle(...values) {
  let state = -1;
  const length = values.length;
  return function () {
    state = (state + 1) % length;
    return values[state];
  };
}

References


12. Create a range function which returns an array for the provided inputs as start and end

js copy
// Example
range(3, 6); // [3, 4, 5, 6]
range(3)(5); // [3, 4, 5]
range(3)(0); // []
  • Range functionality can be obtained by returning the an array from start to end both inclusive
  • In case if 2nd argument is not passed, function will return another function which calls itself with once both the values are obtained
js copy
function range(start, end) {
  if (end === undefined) {
    return function (end) {
      return range(start, end);
    };
  }

  const arr = [];
  for (let i = start; i <= end; i++) {
    arr.push(i);
  }
  return arr;
}

References


13. Write a function which takes a function as an argument to achieve memoization

  • Memoization is an optimization technique used primarily to speed up the programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again
  • Function can be designed to use a cache storage (using map or object) which stores the values of function output against the input
js copy
function memoize(fn) {
  const cache = new Map();
  return function () {
    const key = JSON.stringify(arguments);

    // if the calculations have already been done for inputs, return the value from cache
    if (cache.has(key)) {
      return cache.get(key);
    } else {
      // call the function with arguments and store the result in cache before returning
      cache.set(key, fn(...arguments));
      return cache.get(key);
    }
  };
}

// driver code
let factorial = memoize(function fact(value) {
  return value > 1 ? value * fact(value - 1) : 1;
});

factorial(5); // 120 (output is calculated by calling the function)
factorial(5); // 120 (output is returned from the cache which was stored from previous calculations)

Notes

Stringification of arguments done in order for the function to work for multiple arguments

References


14. Create a single function which can perform sum(a, b, c), sum(a, b)(c), sum(a)(b, c) and sum(a)(b)(c) and returns sum of a, b and c

js copy
// Example
sum(2)(4)(6); // 12
sum(3, 2)(5); // 10
sum(4)(-10, -6); // -12
sum(6, -3, 1); // 4
  • Sum functionality can be obtained by returning the sum when all the arguments are present
  • The cases when only 1 or 2 arguments are passed need to be managed and handled
js copy
function sum(a, b, c) {
  if (a !== undefined && b !== undefined && c !== undefined) {
    return a + b + c;
  }
  if (a !== undefined && b !== undefined) {
    return function (c) {
      return sum(a, b, c);
    };
  }
  return function (b, c) {
    if (b !== undefined && c !== undefined) {
      return sum(a, b, c);
    }
    return function (c) {
      return sum(a, b, c);
    };
  };
}
js copy
const countOfValues = 3;

function sum() {
  const args = arguments;

  if (args.length === countOfValues) {
    return Array.prototype.reduce.call(args, (a, b) => a + b);
  }

  return function () {
    return sum(...args, ...arguments);
  };
}

Notes

2nd approach is generic technique and can be used customized for any number of values


15. Design a function which can keep recieving the arguments on each function call and returns the sum when no argument is passed

  • The function can be designed to return another function which maintains the closure over the previous sum value
  • The check for breaking condition can be added using the argument check for undefined
  • 3rd solution uses the property on function to store the total which will be updated on each call hence the same function can be returned
js copy
// Example
sum(2)(4)(6)(1)(); // 13
sum(2)(4)(); // 6
sum(3)(); // 3
  • Sum functionality can be obtained by returning the recursively calling till the 2nd parameter value is undefined
js copy
function sum(a) {
  return function (b) {
    if (b === undefined) {
      return a;
    }
    return sum(a + b);
  };
}
js copy
const sum = (a) => (b) => b === undefined ? a : sum(a + b);
js copy
function sum(a) {
  if (typeof a === "undefined") {
    return sum.total;
  }
  sum.total = (sum.total ?? 0) + a;
  return sum;
}

Notes

In the code value is checked if it is undefined reason being 0 is a falsy value and b ? a : sum(a + b) code fails when one of the argument is 0. Example: sum(4)(3)(0)(2)()

References


16. Create an interface for a function such that whenever a function is triggered the system should log the time. Do not modify the function code

  • Function call can be handled using Proxy in JavaScript
  • apply keyword in proxy can be used to achieve the functionality without modifying the existing function code
js copy
function generateSecretObject(key, value) {
  return { [key]: value };
}

generateSecretObject = new Proxy(generateSecretObject, {
  apply(target, context, args) {
    console.log(`${target.name} function is accessed at ${new Date()}`);
    return target.apply(context, args);
  },
});

// driver code
const user = {
  username: "0001",
  generateSecretObject,
};
generateSecretObject("username", "Password"); // "generateSecretObject function is accessed at {time}"

Notes

This technique is helpful in logging or managing the data being passed to & returned from function without modifying the actual function code especially when function is a part of library or framework


17. Create an interface exposing subscribe and publish functionality, which allows publishing data which in turn invokes all the subscribers with the data

  • A simple module with publish and subscribe function can be exposed to achieve such functionality
  • List of subscribers can be maintained in an array and can be invoked in loop on each publish
js copy
function pubSub() {
  const subscribers = [];

  function publish(data) {
    subscribers.forEach((subscriber) => subscriber(data));
  }

  function subscribe(fn) {
    subscribers.push(fn);
  }

  return {
    publish,
    subscribe,
  };
}

// driver code
const pubSubObj = pubSub();
pubSubObj.subscribe((data) => {
  console.log("Subscriber 1: " + data);
});
pubSubObj.subscribe((data) => {
  console.log("Subscriber 2: " + data);
});

// all subscribers will be called with the data on publish
pubSubObj.publish("Value is 10");

Notes

This is a well known JavaScript pattern called as Publish/Subscribe Pattern

References


File: web/src/app/challenges/objects/page.mdx

export const metadata = {
title: "Objects | Challenges",
}

1. Display all the keys and values of a nested object

  • typeof operator on value gives the type of value
  • Recursive solution can be used to iterate over all the nested objects
js copy
function keyValuePrinter(obj) {
  for (let key in obj) {
    if (typeof obj[key] !== "object") {
      console.log("[" + key + " : " + obj[key] + "]");
    } else {
      keyValuePrinter(obj[key]);
    }
  }
}

2. Write a program which can empty a given object

  • Object can be emptied by removing all the keys present on it
  • Alternatively, a new object can be created and the prototype of the new object can be set as prototype of old object
js copy
for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    delete obj[key];
  }
}
js copy
const newObj = {};
Object.setPrototypeOf(newObj, obj);

Notes

'obj' is considered to be the object to be emptied


3. Show how a deep copy of an object can be done

  • Deep copy is done by copying all the properties of the object to another object
js copy
Object.assign({}, obj);
js copy
{ ...obj};
js copy
JSON.parse(JSON.stringify(obj));
js copy
function deepCopy(obj) {
  if (!obj) return obj;

  const copyObj = {};
  for (const key in obj) {
    if (typeof obj[key] !== "object" || Array.isArray(obj[key]))
      copyObj[key] = obj[key];
    else copyObj[key] = deepCopy(obj[key]);
  }
  return copyObj;
}

deepCopy(obj);

Notes

3rd solution provided does deep copy of a nested object also but this technique results in loss of data

References


4. Create an array of pair of values (key, value) from an object and store it in a map. Consider the object is not nested

  • As the object is not nested, the key-value pairs can be obtained directly by using Object.entries
  • Map can be initialized with key-value pairs
js copy
const map = new Map(Object.entries(obj));

References


5. Create an object with a property 'marks' which cannot be set to a value less than 0

  • getter and setter on the properties of object can be used to control the read and write behavior
js copy
const obj = { marks: 0 };

Object.defineProperty(obj, "marks", {
  set(value) {
    if (value < 0) throw new Error("Marks cant be less than zero");
    marks = value;
  },
  get() {
    return marks;
  },
});
js copy
const obj = {
  _marks: 0,

  set marks(value) {
    if (value < 0) throw new Error("Marks cant be less than zero");
    this._marks = value;
  },

  get marks() {
    return this._marks;
  },
};

Notes

2nd solution shown directly defines getter and setter for property marks, hence uses another variable to store the data

References


6. Create an object which has a property 'userid' which can only be set once and will be a read only property

  • Property accessor writable to false sets the property to be read only
js copy
function userObjectCreator(id) {
  const obj = {};

  Object.defineProperty(obj, "userid", {
    value: id,
    writable: false,
  });

  return obj;
}

const obj = userObjectCreator(1);

Notes

obj.id is a read only property and does not allow overwriting


7. Stringify an object by excluding the 'password' property

js copy
// Example
const obj = {
  id: 1,
  username: "John",
  password: "secret",
  email: "[email protected]",
};
  • JSON.stringify is the method which can be used for stringification of an object or any other value
  • It accepts 2nd argument which can be a function or array
js copy
JSON.stringify(obj, (key, value) => (key === "password" ? undefined : value)); // {"id":1,"username":"John","email":"[email protected]"}
js copy
JSON.stringify(obj, ["id", "username", "email"]); // {"id":1,"username":"John","email":"[email protected]"}

References


8. Design a function which takes an array as input and returns a function 'next', calling which fetches a value one by one

  • The function returned next will return an object which contains value and done properties
js copy
function makeIterator(array) {
  let nextIndex = 0;
  return {
    next: function () {
      return nextIndex < array.length
        ? {
            value: array[nextIndex++],
            done: false,
          }
        : {
            done: true,
          };
    },
  };
}

// driver code
let it = makeIterator(["yo", "ya"]);
it.next().value; // 'yo'
it.next().value; // 'ya'
it.next().done; // true

References


9. Create an object 'obj' with functions assigned to keys. Show how can we achieve 'obj.func1().func2().func3()' considering func1, func2, func3 are object keys

  • For achieving chaining functionality, each function can return the calling context itself so that context is retained
js copy
var obj = {
  id: 1,
  username: "Jane",
  dept: "Computers",

  displayId() {
    console.log("Id: " + this.id);
    return this;
  },

  displayName() {
    console.log("Name: " + this.username);
    return this;
  },

  displayDept(dept) {
    if (typeof dept !== "undefined") {
      this.dept = dept;
    }
    console.log("Dept: " + this.dept);
    return this;
  },
};

// driver code
obj.displayId().displayName().displayDept("Info Tech");

Notes

Order of calling the functions does not matter as all the functions are returning object itself

References


10. Create an object with property counter which keeps incrementing on every access

js copy
const obj = counterObject();
obj.counter; // 1
obj.counter; // 2
obj.counter; // 3
  • The access to the property of the object can be configured through property getter
  • A separate private variable can be maintained to track the value and getter on each access to increment and return the value
js copy
function counterObject() {
  const symCounter = Symbol("counter");

  const obj = {
    [symCounter]: 0,

    get counter() {
      return ++this[symCounter];
    },

    set counter(value) {
      throw new Error("Cannot set the counter");
    },
  };
  return obj;
}

Notes

Symbol is used to maintain the private variable in the object. Using the private variable to store the data such as _counter is also a well known pattern before symbols


11. Create an object and make it behave like an array which allows push and pop operations on items

  • Object does not have by default a property named 'length' and hence we can define it on object which helps to track the length
  • 'push' and 'pop' functions can be added to the object which internally calls the Array methods push and pop by passing the object context
js copy
const arrayLikeObject = {
  length: 0,
  push: function (item) {
    Array.prototype.push.call(this, item);
  },
  pop: function () {
    Array.prototype.pop.call(this);
  },
};

// driver code
arrayLikeObject.push("first");
arrayLikeObject.push("second");
arrayLikeObject.pop();
arrayLikeObject; // { length: 1, 0: first }

Notes

As the context for array methods is set object, length of the object changes whenever push and pop operations take place


12. Write a function which can be used to deeply compare 2 nested objects

js copy
// Example
const obj1 = {
  name: "John",
  details: {
    x: 1,
    y: 2,
  },
};

const obj2 = {
  name: "John",
  details: {
    y: 2,
    x: 1,
  },
};

deepEqual(obj1, obj2); // true
  • The objects can be deeply compared by checking the key value pairs recursively
js copy
function deepEqual(object1, object2) {
  const keys1 = Object.keys(object1);
  const keys2 = Object.keys(object2);

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (const key of keys1) {
    const val1 = object1[key];
    const val2 = object2[key];
    const areObjects =
      val1 != null &&
      typeof val1 === "object" &&
      val2 != null &&
      typeof val2 === "object";
    if (
      (areObjects && !deepEqual(val1, val2)) ||
      (!areObjects && val1 !== val2)
    ) {
      return false;
    }
  }

  return true;
}

Notes

Stringification of both objects and comparision will also work, but fails on keys order mismatch

References


13. Design a class for employee which takes id and name in during construction of object and has a salary property

  • Classes are a template for creating objects. They encapsulate data with code to work on that data
  • The constructor method is a special method for creating and initializing an object created with a class
  • Objects of the class can be created using new keyword followed by classname
js copy
class Employee {
  constructor(id, name) {
    if (typeof id !== "undefined" && typeof name !== "undefined") {
      this.id = id;
      this.name = name;
    } else
      throw new Error(
        "Employee id and name are mandatory for new employee creation"
      );
  }

  getId() {
    return this.id;
  }

  getName() {
    return this.name;
  }

  setSalary(base, variable) {
    this.salary = base + variable;
  }

  getSalary() {
    return this.salary;
  }
}

// driver code
const emp = new Employee(1, "John Doe");
emp.setSalary(10000, 1000);
emp.getSalary(); // 11000

Notes

Class in JavaScript is a functionality to achieve a class-based model on top of the prototype-based programming model of JavaScript

References


14. Write a program to make all the properties of an object read-only but allow the addition of new properties

  • The existing properties of the object can be made read-only with the set keyword using the Proxy
js copy
const readOnlyObj = new Proxy(obj, {
  get: function (target, key) {
    return target[key];
  },

  set: function (target, key, value) {
    if (target.hasOwnProperty(key)) {
      throw new Error("Object properties are read-only");
    }
    target[key] = value;
  },
});

Notes

If the condition takes care of whether the property is new or existing to handle the read-only scenario

References


15. Write a program that can return a boolean if value is present in the range with given start and end values in an object

js copy
// Example
let range = {
  start: 10,
  end: 50,
};

5 in range; // false
25 in range; // true
  • The object in can be trapped using Proxy trap has, to check if the value is in the range or not
js copy
range = new Proxy(range, {
  has(target, value) {
    return value >= target.start && value <= target.end;
  },
});

js copy
// Example
const tagManager = TagManager();
tagManager.addTags("React", "Redux, JSX, JavaScript, VDOM");
tagManager.addTags("Angular", "RxJS, TypeScript, JavaScript");
tagManager.addTags("Vue", "VDOM, JavaScript");

tagManager.getTopics.getTopics("VDOM"); // React, Vue
tagManager.getTopics.getTopics("JavaScript"); // React, Angular, Vue
  • The tags can be stored as keys and an array of topics as values in a map
  • Function module can be designed to expose 'addTags' and 'getTopics' by tag name
js copy
function TagManager() {
  const map = new Map();

  function addTags(topic, tagText) {
    const tagsArr = tagText.split(",").map((tag) => tag.trim());

    tagsArr.forEach((tag) => {
      if (map.has(tag)) {
        map.get(tag).push(topic);
      } else {
        map.set(tag, [topic]);
      }
    });
  }

  function getTopics(tag) {
    return map.get(tag);
  }

  return {
    addTags,
    getTopics,
  };
}

17. Write a function that accepts a collection of values & an iteratee as arguments and returns a grouped object

js copy
// Example
groupBy([6.1, 4.2, 6.3], Math.floor); // { 6: [6.1, 6.3], 4: [4.2] }
groupBy(["one", "two", "three"], "length"); // { 3: ['one', 'two'], 5: ['three'] }
  • As the 2nd argument is either a function or property, the iteratee can be performed accordingly on the value of arrays
  • An empty object can be created and used to push the values of the array to the respective property of the iteratee output
js copy
function groupBy(values, iteratee) {
  const obj = {};
  for (let value of values) {
    const prop =
      typeof iteratee === "function" ? iteratee(value) : value[iteratee];
    prop in obj ? obj[prop].push(value) : (obj[prop] = [value]);
  }

  return obj;
}

References


18. Create a constructor function that allows its functions present on the prototype to be accessed only by the objects created by calling it

  • The list of objects created by the function can be kept track of using a collection object inside the function
  • Weakset can be a preferred way to use as a collection for objects created through it as the dereferencing of the object helps in garbage collection
  • A context validation within prototype method can be set if the object is created by the function itself or not
js copy
function ProtectedFunction() {
  const objectCollection = new WeakSet();
  objectCollection.add(this);

  if (!ProtectedFunction.prototype.method) {
    ProtectedFunction.prototype.method = function () {
      if (!objectCollection.has(this))
        throw new TypeError("Incompatible object!");
      return "Access granted";
    };
  }
}

// driver code
const protectedObj = new ProtectedFunction();
protectedObj.method(); // Access granted

const obj = {};
ProtectedFunction.prototype.method.call(obj); // Incompatible object!

19. Design a utility on an array of objects where access can be made to the object using the index (as usual) and also from the primary key of the object

js copy
// Example
const employees = [
  { name: "John", id: "1" },
  { name: "Jane", id: "2" },
  { name: "Pai", id: "0" },
];

flexEmployees[0]; // { name: 'John', id: '1' }
flexEmployees["Pai"]; // { name: 'Pai', id: '0' }
flexEmployees["doe"]; // undefined
  • The access to the index happens for arrays by default and the Proxy can be set to enable the fetching of objects using the primary key (any other key can also be coded)
js copy
const flexEmployees = new Proxy(employees, {
  get(target, handler) {
    if (handler in target) {
      return target[handler];
    } else if (typeof handler === "string") {
      return target.find((obj) => obj.name === handler);
    } else {
      return undefined;
    }
  },
});

20. Write a function that receives an object and returns a true if the object has a circular reference

js copy
// Example
var circularReferenceObj = { data: 123 };
circularReferenceObj.myself = circularReferenceObj;
  • Stringification of an object having circular references will throw an error
js copy
function doesObjectHaveCircularRef(obj) {
  try {
    JSON.stringify(obj);
    return false;
  } catch {
    return true;
  }
}

References


21. Write a code that can eliminate circular references in an object (Cyclic reference in an object)

  • Circular/cyclic reference exists when the object property value forms a cycle
  • The circular references can be eliminated by passing a function to take care of circular references during stringification
  • The circular references can also be eliminated by setting such property value to null on the object itself
js copy
const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

JSON.stringify(circularReferenceObj, getCircularReplacer());
js copy
function removeCircularRef(obj) {
  const set = new WeakSet([obj]);

  (function iterateObj(obj = circularReference) {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (typeof obj[key] === "object")
          if (set.has(obj[key])) delete obj[key];
          else {
            set.add(obj[key]);
            iterateObj(obj[key]);
          }
      }
    }
  })();
}

Notes

circularReferenceObj is assumed to be an object with a cyclic reference


22. Provide an object on which a value can be set to nested property even if it does not exist.

  • The nested object can be accessed only if all the nested properties are defined on the object
  • A proxy can designed to create such nested object properties on demand whenever such non-existent property is requested and attempted to set with value
  • get trap of proxy can be used to create the objects dynamically and set the value
js copy
function ProxyObject(obj) {
  return new Proxy(obj, {
    get: (target, property) => {
      if (!(property in target)) {
        target[property] = new ProxyObject({});
      }
      return target[property];
    },
  });
}

// driver code
const obj = new ProxyObject({});
obj.x.y.z = "nested value";

obj.x.y.z; // nested value

File: web/src/app/challenges/primitives/page.mdx

export const metadata = {
title: "Primitives | Challenges",
}

1. Swap two integers present in variables num1 and num2 without using a temporary variable

  • The swapping of 2 variables is possible with simple Destructuring assignment using an array
  • The traditional approach of swapping by using the given variables is also achievable
js copy
let num1 = 10, num2 = 20;
[num1, num2] = [num2, num1];
js copy
let num1 = 10, num2 = 20;
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2;

Notes

2nd solution can fail due to overflow of the number range if the numbers are very big


2. Write a function that returns true if the given value of a number is an integer without using any inbuilt functions

js copy
// Example
isInt(4.0); // true
isInt(12.2); // false
isInt(0.3); // false
  • The modulo operator can be used to check if there is a remainder left when divided by 1
js copy
function isInt(value) {
  return value % 1 === 0;
}

3. Create a function that returns a random number in the given range of values, both inclusive

  • Math.random function returns a floating-point, pseudo-random number between 0 (inclusive) and 1 (exclusive)
js copy
function randomNumberGeneratorInRange(rangeStart, rangeEnd) {
  return rangeStart + Math.floor(Math.random() * (rangeEnd - rangeStart + 1)) 
}

randomNumberGeneratorInRange(10, 50); // 12

Notes

Usage of Math.round depends on the logic used to accomplish the requirement

References


4. Write a program to reverse a string

  • A string can be reversed by iterating over it and storing it in reverse order
  • A string can also be reversed by converting it to an array, then joining it after reversing
js copy
const str = "JavaScript is awesome";
let reversedString = "";
for (let i = 0; i < str.length; i++) {
  reversedString = str.charAt(i) + reversedString;
}

reversedString; // "emosewa si tpircSavaJ"
js copy
const str = "JavaScript is awesome";
str.split("").reverse().join(""); // "emosewa si tpircSavaJ"

Notes

The string can be tested if it is palindrome, by comparing the actual string with the reversed string

References


5. Write a program to reverse a string by words. Also show the reverse of each words in place

  • The string can be reversed by words, by splitting the string with spaces and joining them back after reverse
  • If the the letters in each word have to be reversed, the string reversal procedure has to be followed after breaking the string with spaces
js copy
const str = "JavaScript is awesome";
str.split(" ").reverse().join(" "); // "awesome is JavaScript"
js copy
const str = "JavaScript is awesome";
str
  .split(" ")
  .map((val) => val.split("").reverse().join(""))
  .join(" "); // "tpircSavaJ si emosewa"

6. Write a program to reverse a given integer number

  • The remainder of the number can be fetched and the number can be divided by 10 to remove the digit in loop till number becomes 0
  • A simple approach to reverse a number could also be to convert it in to a string and then reverse it
js copy
let num = 3849;

let reversedNum = 0;
while (num !== 0) {
  reversedNum = reversedNum * 10 + (num % 10);
  num = Math.floor(num / 10);
}

reversedNum; // 9483
js copy
let num = 3849;

let numStr = String(num);
+numStr.split("").reverse().join(""); // 9483

7. Write a code to replace all the spaces of the string with underscores

  • The string can be split using the space character and can be joined back with underscore to replace all the spaces with strings
  • replaceAll is the inbuilt String function on prototype which can be used to replace a string with another string
js copy
str.split(" ").join("_");
js copy
str.replaceAll(" ", "_");

Notes

replace is also an inbuilt String function on prototype which can be used to replace the 1st occurrence of the string with another string

References


8. Write a function which can convert the time input given in 12 hours format to 24 hours format

js copy
// Example
convertTo24HrsFormat("12:10AM"); // 00:10
convertTo24HrsFormat("5:00AM"); // 05:00
convertTo24HrsFormat("12:33PM"); // 12:33
convertTo24HrsFormat("01:59PM"); // 13:59
convertTo24HrsFormat("11:8PM"); // 23:08
convertTo24HrsFormat("10:02PM"); // 22:02
  • The check for 'AM' and 'PM' can be verified using endsWith String method
  • An extra 0 would be needed if the hours have single digit
js copy
function convertTo24HrsFormat(timeText) {
  var timeTextLower = timeText.toLowerCase();
  let [hours, mins] = timeTextLower.split(":");

  // 12 o clock is the special case to be handled both for AM and PM
  if (timeTextLower.endsWith("am")) hours = hours == 12 ? "0" : hours;
  else if (timeTextLower.endsWith("pm"))
    hours = hours == 12 ? hours : String(+hours + 12);

  return hours.padStart(2, 0) + ":" + mins.slice(0, -2).padStart(2, 0);
}

Notes

Conversion of string to lowerCase helps in case insensitive comparision

References


9. Write a function which accepts a string argument and returns the count of characters between the first and last character 'X'

js copy
// Example
getTheGapX("XeroX"); // 4
getTheGapX("Xamarin"); // -1       (If there is only single character 'X')
getTheGapX("JavaScript"); // -1       (If there is no character 'X')
getTheGapX("F(X) !== G(X) !== F(X)"); // 18
  • indexOf and lastIndexOf are the methods on String which returns the position of the given string in the input string from start and end respectively
  • If the match is not found, these methods return -1
js copy
function getTheGapX(str) {
  if (!str.includes("X")) {
    return -1;
  }

  const firstIndex = str.indexOf("X");
  const lastIndex = str.lastIndexOf("X");
  return firstIndex === lastIndex ? -1 : lastIndex - firstIndex;
}

10. Write a function to truncate a string to a certain number of letters

js copy
// Example
truncateString("JavaScript", 7); // "Java..."
truncateString("JS is fun", 10); // "JS is fun"
truncateString("JS is funny", 10); // "JS is f..."
  • Text can be truncated by fetching the substring from start till the count of characters
  • substr methods of String can be used to fetch the part of the string
js copy
function truncateString(str, charCount) {
  if (str.length > charCount) {
    return str.substr(0, charCount - 3) + "...";
  } else {
    return str;
  }
}

11. Write a code to truncate a string to a certain number of words

  • The string can be broken in to words array and then slice method of array can be used to get the number of words which will then be joined back
js copy
const str = "JavaScript is simple but not easy to master";
const wordLimit = 3;

str.split(" ").slice(0, wordLimit).join(" "); // "JavaScript is simple"

12. Create a regular expression to validate if the given input is valid Indian mobile number or not

js copy
// Example
validateMobile("+919876543210"); // true
validateMobile("+91 9876543210"); // true
validateMobile("09876543210"); // true
validateMobile("9876543210"); // true
validateMobile("99876543210"); // false
  • Regular expression check has to have an optional +91 or 0 in the beginning, then an optional space and 10 digits
  • test method of regular expression can be used to validate if the mobile number pattern matches or not
js copy
function validateMobile(str) {
  const regexMobile = /^(\+91|0)?\s?\d{10}$/;
  return regexMobile.test(str);
}
js copy
function validateMobile(str) {
  const regexMobile = /^(\+91|0)?\s?\d{10}$/;
  return str.match(regexMobile) !== null;
}

Notes

String has method match which returns array of matches or null


13. Write a function which returns a list of elements which contains at least one character as digit

js copy
// Example
numInStr(['1a', 'a', '2b', 'b']));              // ['1a', '2b']
numInStr(['abc', 'abc10']));                    // ['abc10']
numInStr(['abc', 'ab10c', 'a10bc', 'bcd']));    // ['ab10c', 'a10bc']
numInStr(['this is a test', 'test1']));         // ['test1']
  • A test for digit after looping through the array would give the list of values having at least one digit string
js copy
function numInStr(mixArray) {
  return mixArray.filter((value) => {
    return /[0-9]/.test(value);
  });
}

14. Write a function which checks if a given search text is present either in the beginning of the first name or the second name

js copy
// Example
validateName("Nedson PETER", "pet"); // true
validateName("Peter Parker", "pet"); // true
validateName("Speter parker", "pet"); // false
validateName("John Doe Peter", "pet"); // false
  • The function can be designed to accept the name and the search text
  • Regular expression can be designed to validate if the name has search text the beginning of first or second name
js copy
function validateName(str, searchText) {
  const regex = new RegExp("^(\\w*\\s)?" + searchText + "\\w*?", "i");
  return regex.test(str);
}

Notes

Case insensitive match is happening for the search text in the string represented by the argument "i" for the regular expression


15. Write a function to chop a string into chunks of a given length and return it as array

js copy
// Example
stringChop("JavaScript"); // ["JavaScript"]
stringChop("JavaScript", 2); // ["Ja", "va", "Sc", "ri", "pt"]
stringChop("JavaScript", 3); // ["Jav", "aSc", "rip", "t"]
  • String can be chopped using slice method of String
  • Regular expression can also be used effectively to this operation
js copy
function stringChop(str, size = str.length) {
  const arr = [];
  let i = 0;
  while (i < str.length) {
    arr.push(str.slice(i, i + size));
    i = i + size;
  }
  return arr;
}
js copy
function stringChop(str, size = str.length) {
  return str.match(new RegExp(".{1," + size + "}", "g"));
}

References


16. Write a code to remove all the vowels from a given string

  • replace method on String accepts a string or regex as the argument
js copy
const str = "I love JavaScript";
str.replace(/[aeiou]/gi, ""); // _lv_JvScrpt

References


17. Create a function which returns random hex color code

  • The color code is popularly represented in hexadecimal format for RGB colors
  • The minimum value for the color is '#000000' and maximum is '#FFFFFF'
js copy
function getGetHEXColorCode() {
  const rValue = Math.round(0xff * Math.random())
    .toString(16)
    .padStart(2, "0");
  const gValue = Math.round(0xff * Math.random())
    .toString(16)
    .padStart(2, "0");
  const bValue = Math.round(0xff * Math.random())
    .toString(16)
    .padStart(2, "0");
  return "#" + rValue + gValue + bValue;
}

Notes

toString method on String takes optional parameter which converts converts to the specified base before converting to string

References


18. Write a function which accepts two valid dates and returns the difference between them as number of days

  • The difference between 2 dates in JavaScript will give the time difference in milliseconds
  • Time difference can be converted in to days by dividing the 24Hrs time in milliseconds
js copy
const DAY_IN_MILLISECONDS = 1000 * 60 * 60 * 24;

function getDaysBetweenDates(dateText1, dateText2) {
  const date1 = new Date(dateText1);
  const date2 = new Date(dateText2);
  const diffTime = Math.abs(date2 - date1);
  const diffDays = Math.ceil(diffTime / DAY_IN_MILLISECONDS);
  return diffDays;
}

getDaysBetweenDates("10/15/2020", "12/1/2020"); // 47

References


19. How can you detect NaN in JavaScript?

NaN is a special numeric value in JavaScript that indicates "Not-a-Number." You can use Number.isNaN() or isNaN() to check for NaN, though they behave differently.

javascript
console.log(Number.isNaN(NaN));           // true
console.log(Number.isNaN("hello"));       // false (doesn't coerce)
console.log(Number.isNaN(undefined));     // false

console.log(isNaN(NaN));                  // true
console.log(isNaN("hello"));              // true (coerces to NaN)
console.log(isNaN(undefined));            // true (coerces to NaN)

References


20. Show how to use Object.is for equality comparison between primitives

Object.is can be used to check strict equality between two values, especially in edge cases like NaN, 0 and -0, where === may behave differently.

javascript
console.log(Object.is(10, 10));               // true
console.log(Object.is("hello", "hello"));     // true
console.log(Object.is(NaN, NaN));             // true (different from ===)
console.log(Object.is(0, -0));                // false (different from ===)
console.log(Object.is(null, null));           // true
console.log(Object.is(undefined, undefined)); // true
console.log(Object.is(Symbol(), Symbol()));   // false (different symbols are unique)

References



File: web/src/app/concepts/async/page.mdx

export const metadata = {
title: "Async | Concepts",
}

1. Show the execution of 3 asynchronous block of code, one after the other in sequence

  • The asynchronous block of code can be a function which executes asynchronously
  • The execution of such function can be simulated using setTimeout to with delay and execute different blocks of code inside each
js copy
function asyncFunc() {
  console.log("Started asyncFunc1");
  //Async1 code
  setTimeout(() => {
    console.log("Completed asyncFunc1");
    console.log("Started asyncFunc2");
    //Async2 code
    setTimeout(() => {
      console.log("Completed asyncFunc2");
      console.log("Started asyncFunc3");
      //Async3 function code
      setTimeout(() => {
        console.log("Completed asyncFunc3");
      }, 1000);
    }, 2000);
  }, 3000);
}
asyncFunc();

Notes

The nested blocks of statements shown in the comments which get executed one after the other in sequence


2. Write a code to make xmlHTTPRequest to get data from the server asynchronously

  • XMLHttpRequest (XHR) objects are used to interact with server to retrieve data from a URL without having to do a full page refresh
  • XHR requests can be initiated by creating the object and providing the arguments such as 'method', url etc
  • The success and failure of the request can be managed by callbacks
js copy
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
  console.log(this.response);
};
xhr.onerror = function () {
  console.log(this.statusText);
};
xhr.send();

Notes

XHR is used mainly in AJAX programming

References


3. Show the working of promise along with resolve & reject code

  • The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value
  • Promise returns an object which remains in pending state until it is resolved or rejected
  • Promise takes a function as an argument called as 'resolver' which can have resolve and reject as parameters
  • Resolve call will resolve the promise and reject will reject the promise (passing data is optional)
  • then method on promise object is used to execute the user code after promise settles, which takes functions where 1st one is for success and 2nd for failure
  • Functions with success and failure of the promises are used to illustrate the basics of promise code
js copy
function asyncResolveFunc() {
  function resolver(resolve, reject) {
    resolve("Success");
  }
  return new Promise(resolver);
}
function asyncRejectFunc() {
  function resolver(resolve, reject) {
    reject("Failure");
  }
  return new Promise(resolver);
}
// driver code
const promiseSuccess = asyncResolveFunc();
const promiseFailure = asyncRejectFunc();
// Succeeded promise .then executes first function passed as argument
promiseSuccess.then(
  (successData) => {
    console.log(successData);
  },
  (failureData) => {
    console.log(failureData);
  }
);
// Failed promise .then executes second function passed as argument
promiseFailure.then(
  (successData) => {
    console.log(successData);
  },
  (failureData) => {
    console.log(failureData);
  }
);

Notes

Once the promise is resolved or rejected, status will not change

References


4. Wrap the setTimeout function to convert to a promise

  • Promise can be used to wrap the setTimeout to make the code more readable
  • Function can take delay as argument and return a promise which gets resolved after timeout is complete
js copy
function setTimeoutPromise(delay) {
  function resolver(resolve) {
    setTimeout(resolve, delay);
  }
  return new Promise(resolver);
}
// driver code
console.log("Task started");
const timeoutPromise = setTimeoutPromise(3000);
timeoutPromise.then(() => {
  console.log("Task completed");
});

References


5. Convert the xmlHTTPRequest to promise based function to get the data from the server asynchronously (fetch)

  • The Promise can be used to wrap the XHR request and provide cleaner interface to user for AJAX requests
  • Success and failure of the XHR request can be handled to resolve or reject the promise respectively
js copy
function fetchData(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = function () {
      try {
        if (this.status === 200) {
          resolve(this);
        } else {
          reject(this);
        }
      } catch (e) {
        reject(e);
      }
    };
    xhr.onerror = function () {
      reject(this);
    };
    xhr.send();
  });
}
// driver code
fetchData("https://reqbin.com/echo/get/json")
  .then((data) => {
    console.log(data);
  })
  .catch((err) => console.log(err));

Notes

XHR request is no more in use and all the modern browsers use fetch API which is based on promise

References


6. Make a fetch request to retrieve and store JSON data from server

  • Fetch API is provided by the browser which returns a promise
  • Fetch takes url as the 1st argument and an object with request details as 2nd optional argument
  • Response is a streamable object and hence we will have to invoke JSON / text method on it which returns promise which settles to the data
js copy
const response = fetch("https://reqbin.com/echo/get/json", {
  method: "GET", // *GET, POST, PUT, DELETE, etc
  headers: {
    "Content-Type": "application/json", // header
  },
});
// driver code
response
  .then((response) => {
    const responseData = response.json();
    responseData.then((data) => {
      console.log(data);
    });
  })
  .catch((err) => {
    console.log(err);
  });

References


7. Cancel a fetch request

  • AbortController is an interface which can be used to abort a fetch request
  • signal object of the AbortController object can be used as the part of the argument to fetch and abort on controller object can be used to stop the request
js copy
const controller = new AbortController();
var signal = controller.signal;
fetch(url, { signal })
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.warn(err);
  });
controller.abort();

References


8. Show the working of async await work with promises

  • async functions are asynchronous functions in which the asynchronous code can be executed in synchronous looking manner using await
  • await expects a promise and the execution will stop until the promise is resolved
  • If promise gets rejected, error is thrown with failure reason which can be handled using simple try-catch block
js copy
async function asyncAwaitFunc() {
  try {
    console.log("Executes normally when invoked");
    await promiseReturningFunc();
    console.log("Continues the execution after promise resolution");
  } catch (err) {
    console.log("Error occured: " + err);
  }
}

Notes

await keyword can only be used in a async function

References


9. Write a code to resolve all the list of asynchronous executions of promises and stop if any of them is rejected. Print the output accordingly

  • Promise.all is the method which helps to achieve the functionality which settles if all the promises are resolved or any of them are rejected
  • It receives array of promises as an argument to it
  • Array of results will be the success data if all the promises resolves or the error data on failure of the first one
js copy
const asyncArr = [async1, async2, async3];
const promiseArr = asyncArr.map((async) => async());
finalResolution = Promise.all(promiseArr);
finalResolution
  .then((output) => {
    for (let data of output) {
      console.log(data);
    }
  })
  .catch((err) => console.log(err));
js copy
const asyncArr = [async1, async2, async3];
const promiseArr = asyncArr.map((async) => async());
(async function () {
  try {
    output = await Promise.all(promiseArr);
    for (let data of output) {
      console.log(data);
    }
  } catch (err) {
    console.log(err);
  }
})();

Notes

On failure of one of the promise, rest of the pending promises will be cancelled

References


10. Write a code to resolve all the list of asynchronous executions of promises no matter if each execution succeeds or fails. Print the output of each

  • Promise.allSettled is the method which helps to achieve the functionality which completes after all promises settle no matter of failures
  • It receives array of promises as an argument to it
  • Array of results will be the output after completion of all promises with status as 'fulfilled' or 'rejected'
js copy
const asyncArr = [async1, async2, async3];
const promiseArr = asyncArr.map((async) => async());
finalResolution = Promise.allSettled(promiseArr);
finalResolution
  .then((output) => {
    for (let data of output) {
      if (data.status === "fulfilled")
        console.log(data.status + ": " + data.value);
      else if (data.status === "rejected")
        console.log(data.status + ": " + data.reason);
    }
  })
  .catch((err) => {
    console.log(err);
  });
js copy
const asyncArr = [async1, async2, async3];
const promiseArr = asyncArr.map((async) => async());
(async function () {
  try {
    output = await Promise.allSettled(promiseArr);
    for (let data of output) {
      if (data.status === "fulfilled")
        console.log(data.status + ": " + data.value);
      else if (data.status === "rejected")
        console.log(data.status + ": " + data.reason);
    }
  } catch (err) {
    console.log(err);
  }
})();

References


11. Explain the working of Promise.race with few asynchronous function example

  • The Promise.race method returns a promise that fulfills or rejects as soon as one of the promises fulfills or rejects, with the success or failure
js copy
function asyncFunc1() {
  return new Promise((resolve) =>
    setTimeout(() => {
      resolve("Resolved async1");
    }, 2000)
  );
}
function asyncFunc2() {
  return new Promise((resolve) =>
    setTimeout(() => {
      resolve("Resolved async2");
    }, 3000)
  );
}
function asyncFunc3() {
  return new Promise((resolve, reject) =>
    setTimeout(() => {
      reject("Rejected async3");
    }, 1000)
  );
}
// driver code
const asyncArr = [asyncFunc1, asyncFunc2, asyncFunc3];
const promiseArr = asyncArr.map((async) => async());
Promise.race(promiseArr).then(console.log).catch(console.log); // Rejected async3 (catch block)

References


12. Show me the working of a generator function

  • Generators are functions that can be exited and later re-entered
  • Generator function will have * after the keyword function
  • Generator when called returns an iterator which can be used to call next on it
  • yield keyword can be used inside such a function and stops the execution
js copy
function* generatorFunc(param) {
  const num1 = yield;
  const num2 = yield;
  return num1 + num2;
}
// driver code
const it = generatorFunc();
it.next(); // { value: undefined, done: false}
it.next(3); // { value: undefined, done: false}
const sum = it.next(5); // { value: 8, done: true }
sum.value; // 8

Notes

Data between generator and iterator can be passed in both direction

References


13. Write a generator function which uses another generator function internally to fetch the values. Use for..of loop to consume the values

  • Generator with the generator can be used to fetch the values using yield*
  • The code consuming the parent generator need to be aware of it and can be used directly
  • As the generator return iterator, for..of loop can be used on generator
js copy
function* gen1() {
  yield 1;
  yield* gen2();
  yield 4;
}
function* gen2() {
  yield 2;
  yield 3;
}
// driver code
for (let value of gen1()) {
  console.log(value);
}

References


14. Write an interface to mock Promise in JavaScript which can be called to create a promise with resolve and reject. Also implement then functionality

  • Basic promise interface will allow creation of promise by passing resolver as the argument
  • resolve and reject methods will have to be passed to the resolver which the user code will ivoke with data once settled
  • setTimeout with zero delay can be used to not immediately execute the resolver
  • List of callbacks to then to be invoked can be stores in the array of success and failure list
  • Once resolved or rejected, promise cannot change the state
js copy
function MyPromise(resolver) {
  let successList = [];
  let failureList = [];
  let resolution = "pending";
  let data;
  function resolve(value) {
    if (resolution === "pending") {
      for (let successCb of successList) {
        successCb(value);
      }
      resolution = "resolved";
      data = value;
    }
  }
  function reject(value) {
    if (resolution === "pending") {
      for (let failureCb of failureList) {
        failureCb(value);
      }
      resolution = "rejected";
      data = value;
    }
  }
  setTimeout(() => {
    try {
      resolver(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }, 0);
  return {
    status: resolution,
    then: function (onSuccess, onFailure) {
      if (resolution === "pending") {
        successList.push(onSuccess);
        failureList.push(onFailure);
      } else {
        resolution === "resolved" ? onSuccess(data) : onFailure(data);
      }
    },
  };
}
// driver code
let p = new MyPromise((resolve, reject) => {
  resolve(10);
});
p.then((data) => console.log(data), console.log);

Notes

ES6 Promise is much more complex and sophesticated than the above shown implementation.


15. Write a function which helps to achieve the `Promise.all` functionality using promises

  • Promise.all method is fail fast procedure to return all the promise resolved data in array or failed reason
js copy
function PromiseAll(promiseArr) {
  return new Promise((resolve, reject) => {
    const dataArr = new Array(promiseArr.length);
    let resolution = "pending";
    for (let index in promiseArr) {
      promiseArr[index].then(
        (data) => {
          if (resolution === "pending") {
            dataArr[index] = {
              value: data,
              status: "fulfilled",
            };
            if (!dataArr.includes(undefined)) {
              resolution = "fulfilled";
              resolve(dataArr);
            }
          }
        },
        (err) => {
          if (resolution === "pending") {
            resolution = "rejected";
            reject({
              reason: err,
              status: "rejected",
            });
          }
        }
      );
    }
  });
}
// driver code
PromiseAll([
  new Promise((resolve) => setTimeout(resolve, 1000)),
  new Promise((resolve, reject) => setTimeout(reject, 2000)),
]).then(console.log, console.log);

16. Show the working generator function with promises

  • Generator can be used with promises where yield will return a promise and promise resolution can trigger continuation
  • Helper function is used to manage this flow which takes generator function as an argument and executes it
js copy
// asynchronous helper function returning a promise which gets resolved after the specified delay with data
function asyncFunc(data, delay) {
  return new Promise((resolve) => setTimeout(resolve, delay, data));
}
function* gen() {
  // async function calls to yield promise
  const num1 = yield asyncFunc(2, 1000);
  const num2 = yield asyncFunc(1, 2000);
  console.log(num1 + num2); // 3 (2 + 1)
}
function executeGeneratorWithPromise(gen) {
  const it = gen();
  // takes input as promise from generator
  function handle(promise) {
    if (!promise.done)
      promise.value
        .then((data) => {
          // continue the execution of generator after promise is resolved
          handle(it.next(data));
        })
        .catch((err) => iterator.throw(err));
  }
  handle(it.next());
}
// call generator executor function and pass generator function reference
executeGeneratorWithPromise(gen);

Notes

The generator and the helper function 'executeGeneratorWithPromise' executes hand in hand, where the generator pauses returning a promise and the helper function starts generator on that promise resolution

References


File: web/src/app/concepts/collections/page.mdx

export const metadata = {
title: "Collections | Concepts"
}

1. Show the different ways of creating an array

  • Arrays are the collection of values in javascript. Array is a special type of object in JavaScript
  • Arrays values are indexed from 0 and have special property length which stores the count of elements present in array
js copy
// literal form
const arr = [];
js copy
// constructor form
const arr = new Array();
js copy
// pre defined number of slots
const arr = new Array(10);
js copy
// with values
const arr = [1, true, "string"];
js copy
// constructor form with values
const arr = new Array(1, true, "string");

References


2. Write a program to iterate over an array and print all the values of it

  • Arrays can be iterated by using its index to fetch the values
  • Arrays also can be iterated with for each style loops
js copy
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
js copy
for (let index in arr) {
  console.log(arr[index]);
}
js copy
for (let value of arr) {
  console.log(value);
}
js copy
arr.forEach((val) => console.log(val));

3. Write a program to append and prepend, single or multiple values in to an array

  • Values to the array can be appended using push method of array
  • Values to the array can be prepended using unshift method of array
js copy
const arr = [2, 3];
arr.push(4); // [2, 3, 4]
arr.unshift(1); // [1, 2, 3, 4]
js copy
const arr = [3, 4];
arr.push(5, 6); // [3, 4, 5, 6]
arr.unshift(1, 2); // [1, 2, 3, 4, 5, 6]
js copy
const arr = [1, 2, 3];
const otherArr = [4, 5, 6];
arr.push(...otherArr); // [1, 2, 3, 4, 5, 6]
arr.unshift(...otherArr); // [4, 5, 6, 1, 2, 3, 4, 5, 6]

Notes

To remove the elements from the end of the array pop operation can be used but one element at a time. To remove the elements from the start of the array shift operation can be used but one element at a time

References


4. Show insertion and removal of elements can happen in the array for given index

  • Values of the array can be removed from any position using splice method of array
  • Values of the array can also be inserted to any position using splice method of array
  • 2nd argument is passed as 0 which inserts the elements without replacing
  • The values passed after 2nd argument are considered for insertion
js copy
const arr = [1, 2, 2, 3];
const position = 2;
const count = 1;
arr.splice(position, count); // [2]
console.log(arr); // [1, 2, 3]
js copy
const arr = [1, 2, 4, 5];
const position = 2;
arr.splice(position, 0, 3);
console.log(arr); // [1, 2, 3, 4, 5]

Notes

'count' indicates the number of elements to be removed from the index 'position'. Multiple values can be inserted or removed using splice

References


5. Show the different ways of emptying an array which has values

  • Array can be emptied by giving a new reference of an empty array
  • Setting the length of the array to 0 will automatically makes the array empty
  • pop and shift operation on array can also be used to empty the array where each elements get removed
js copy
arr = [];
js copy
arr = new Array();
js copy
arr.length = 0;
js copy
while (arr.length > 0) {
  arr.pop();
}
js copy
while (arr.length > 0) {
  arr.shift();
}
js copy
arr.splice(0, arr.length);

Notes

splice operation used here to empty the array is a trick by passing the length of the array as argument, where all the elements of the array get removed

References


6. Check if given input is an array or not

  • Array.isArray is a method which checks if the given argument is an array or not
  • Alternatively the toString method present on Object prototype can be used to check if it is an array
js copy
Array.isArray(arr);
js copy
Object.prototype.toString.call(arr) === "[object Array]";

Notes

typeof operator cannot be used to check if a value is an array or not because array is an object and typeof arr returns us "object"

References


7. Show how an array in JavaScript can act like a stack and queue

  • Stack is a 'Last In First Out' data structure can be achieved using push and pop operations
  • Queue is a 'First In First Out' data structure can be achieved using push and shift operations
js copy
// To add the value to the stack
arr.push(value);

// To remove the value from the stack
arr.pop();
js copy
// To add the value to the queue
arr.push(value);

// To remove the value from the queue
arr.shift();

8. Create an array by removing all the holes of the array

  • Holes are undefined value present inside array
  • Holes do not get iterated in filter which will just fetch all the values except undefined
js copy
const uniqueArr = arr.filter((value) => true);

Notes

Holes can be formed when an array value by index is deleted. Example: delete arr[index]


9. Optimize the given statements having lot of logical checks to use a compact and cleaner logic

js copy
// Example1
browser === "chrome" ||
  browser === "firefox" ||
  browser === "IE" ||
  browser === "safari";

// Example2
browser !== "chrome" &&
  browser !== "firefox" &&
  browser !== "IE" &&
  browser !== "safari";
  • Examples can be modified to store the values of comparision in an array and check for the presence of value if it is present inside array
js copy
// Example1
// browser === "chrome" || browser === "firefox" || browser === "IE" || browser === "safari"

const browserList = ["chrome", "firefox", "IE", "safari"];
browserList.includes(browser);
js copy
// Example2
// browser !== "chrome" && browser !== "firefox" && browser !== "IE" && browser !== "safari"

const browserList = ["chrome", "firefox", "IE", "safari"];
!browserList.includes(browser);

Notes

Generally this use case can be implemented for if conditions


10. Write a program to iterate over a 2 dimensional array and print all the values of it

  • Arrays can be iterated by using its index to fetch the values
  • Arrays also can be iterated with for each style loops, with one loop to iterate the rows and inside it for cells
js copy
for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr[i].length; j++) {
    console.log(arr[i][j]);
  }
}
js copy
for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr[i].length; j++) {
    console.log(arr[i][j]);
  }
}
js copy
for (let rowArr of arr) {
  for (let value of rowArr) {
    console.log(value);
  }
}
js copy
arr.forEach((rowArr) => rowArr.forEach((val) => console.log(val)));

11. Write a program to store values in to a set

  • Set lets us store unique values of any type
  • Set can be created empty & then added with values or can be initialized also
js copy
const set = new Set();
set.add(1);
set.add(true);
set.add("text");
set.add(1);

set; // 1, true, "text"
js copy
const set = new Set([1, 2, 3]);

set; // 1, 2, 3

References


12. Write a program to store values in to a map

  • Map holds key-value pairs and remembers the original insertion order of the keys
  • Map can be created empty & then added with values or can be initialized also with key-value pairs
js copy
const map = new Map();
map.set(1, 1000);
map.set(true, false);
map.set("text", "String");

map; // [1, 1000] [true, false] ["text", "String"]
js copy
const map = new Map([
  [1, "One"],
  [2, "two"],
  [3, "three"],
]);
map; // [1, "One"] [2, "two"] [3, "three"]

Notes

Unlike objects, Map can have any primitive or object as the key

References


13. Write a code to iterate over a set

  • set is an iterable object and can be iterated using for..of loop
  • set can also be iterated by simple forEach loop
js copy
for (let val of set) console.log(val);
js copy
set.forEach((value) => console.log(value));

14. Write a code to iterate over a map

  • map is an iterable object and can be iterated using for..of loop
  • map can also be iterated by simple forEach loop
js copy
for (let val of map) console.log(val[0], val[1]);
js copy
for (let key of map.keys()) console.log(key, map.get(key));
js copy
map.forEach((value, key) => console.log(key, value));

15. Show how map is different from object to store key value pairs with coding example

  • Map does not contain any keys by default unlike objects which has keys from its prototype
  • Map's keys can be any value (including functions, objects, or any primitive) unlike object where keys are only strings
  • The keys in Map are ordered in a simple, straightforward way
  • The number of items in a Map is easily retrieved from its size property
  • Map is an iterable object
js copy
map.set(1, "Mapped to a number"); // primitive number as key
map.set("1", "Mapped to a string"); // string value as key
map.set({}, "Mapped to a object"); // object as key
map.set([], "Mapped to an array"); // array as key
map.set(() => {}, "Mapped to a function"); // function as key

Notes

Maps perform better than objects in most of the scenarios involving addition and removal of keys


16. Write a program to polyfill `filter` functionality of the Array

  • filter iterates over the all values of array and passes value, index and array (itself) as the arguments
  • Function returns a new array which filtering the values of the original array
js copy
if (!Array.prototype.filter) {
  Array.prototype.filter = function (callback) {
    if (typeof callback !== "function")
      throw new Error("Argument passed has to be a function");

    let newArray = [];

    for (let index in this) {
      if (callback(this[index], index, this)) {
        newArray.push(this[index]);
      }
    }
    return newArray;
  };
}

Notes

The solution is a simple polyfill of filter and not intended to handle all the corner scenarios


17. Write a program to polyfill `map` functionality of the Array

  • map iterates over the all values of array and passes value, index and array (itself) as the arguments
  • Function returns a new array which is same as the length of the original array
js copy
if (!Array.prototype.map) {
  Array.prototype.map = function (callback) {
    if (typeof callback !== "function")
      throw new Error("Argument passed has to be a function");

    let newArray = [];

    for (let index in this) {
      newArray.push(callback(this[index], index, this));
    }
    return newArray;
  };
}

Notes

The solution is a simple polyfill of map and not intended to handle all the corner scenarios


18. Write a program to polyfill `reduce` functionality of the Array

  • reduce iterates over the all values of array and passes value, index and array (itself) as the arguments
  • reduce accepts an optional initial value which when not provided can be skipped
  • Function returns a single value after all the iteration
js copy
if (!Array.prototype.reduce) {
  Array.prototype.reduce = function (callback, init) {
    let startPosition = 0;
    let accumulator = init ?? this[startPosition++];

    for (let index = startPosition; index < this.length; index++) {
      accumulator = callback(accumulator, this[index], index, this);
    }
    return accumulator;
  };
}

Notes

The solution is a simple polyfill of reduce and not intended to handle all the corner scenarios


File: web/src/app/concepts/functions/page.mdx

export const metadata = {
title: "Functions | Concepts"
}

1. Write a function which returns another function and execute it after calling

  • Functions can be declared, executed or returned inside another function
js copy
function higherOrderFunction() {
  function displayHello() {
    console.log("Hello");
  }
  return displayHello;
}

// driver code
var func = higherOrderFunction();
func(); // Hello

Notes

Functions can also be stored in variables like other values in JavaScript

References


2. Write a function which executes another function received as an argument

  • Functions can be passed as arguments to another function
  • Passing the function as an argument will pass its reference hence no parenthesis
js copy
function callbackExecutor(callback) {
  if (typeof callback === "function") {
    callback();
  }
}

// driver code
function callbackFunc() {
  console.log("Callback function executed");
}

callbackExecutor(callbackFunc); // Callback function executed

References


3. Create a function having no parameters declared and print all the arguments passed to it

  • When a function is invoked the arguments passed to it are accessible using the default object called "arguments"
  • Numbers starting from 0 are set as keys of the object "arguments" corresponding to each argument in the order
  • The arguments object will have a length property as well which gives count of arguments passed
js copy
function func() {
  for (let key in arguments) {
    console.log(arguments[key]);
  }
}

// driver code
func(1, "Hello", true);
js copy
function func() {
  for (let value of arguments) {
    console.log(value);
  }
}

// driver code
func(1, "Hello", true);

Notes

Though the keys of arguments object look like numbers, "arguments" is not an array. Arrow functions will not have arguments object

References


4. Write a function which executes only if the number of arguments match the number of parameters the function is expecting

  • The number of parameters declared in a function can be obtained by accessing the length property of the function
js copy
function func(a, b, c) {
  if (func.length === arguments.length) {
    console.log("Number of arguments passed match the expected arguments");
  } else {
    throw new Error(
      "Number of arguments passed do not match the expected arguments"
    );
  }
}

References


5. Design a function which can receive a variable number of arguments in parameters and print them

js copy
function varArgsFunc(...params) {
  params.forEach(function (value, index) {
    console.log(index, ": ", value);
  });
}

// driver code
varArgsFunc("Hello", ",", "World", "!!!");

References


6. Show the most common ways of creating functions in JavaScript

  • Functions are most commonly created using function statements, function expressions and arrow functions
  • Function statements get hoisted unlike function expressions
js copy
// Regular function as a function statement
function functionName(params) {
  //code block
}
js copy
// Regular function as a function expression
const functionName = function (params) {
  //code block
};
js copy
// Arrow function as a function expression
const arrowFunctionName = (params) => {
  //code block
};

Notes

As the arrow functions are not verbose, majority of developers prefer to create arrow functions for quick coding

References


7. Code the different forms of arrow functions for varying number of parameters

  • Arrow functions provide simpler syntax over function keyword functions
  • Arrow functions with single parameter, round brackets are optional
  • Arrow functions with single statement with return, flower brackets and return keywords are optional
js copy
const noArgsFunc = () => {
  return "No args passed";
};
js copy
const singleArgFunc = (arg1) => "Argument is " + arg1;
js copy
const singleArgFunc = (arg1) => {
  console.log("Argument is " + arg1);
  return arg1;
};
js copy
const twoArgsFunc = (arg1, arg2) => {
  return arg1 + arg2;
};
js copy
const threeArgsFunc = (arg1, arg2, arg3) => {
  console.log("Sum is " + (arg1 + arg2 + arg3));
  return true;
};

Notes

Arrow functions are also called fat arrow functions

References


8. Write a program where hoisting can be visualized

  • The function statement and variable declared with var are accessible before they appear in the code
  • Declarations are put into memory before it executes any code segment that allows us to use a function before you declare it in your code
  • In hoisting the hoisted items are accessible in the scope they are declared in
  • Function expressions do not get hoisted
js copy
num1 = 10;
printHello();

var num1;
function printHello() {
  console.log("Hello");
}

var nonHoistedFunc = function () {
  console.log("Hello");
};

Notes

Hoisting was thought up as a general way of thinking about how execution contexts work in JavaScript. In reality, the code does not get hoisted, but the effect is seen due to compilation and execution phases followed by JavaScript compiler

References


9. Code an Immediately Invoked Function Expression (IIFE) and show the different ways of executing it

  • IIFE is a JavaScript function that runs as soon as it is defined
  • IIFE prevents polluting the global scope
js copy
(function IIFE() {
  console.log("I am an Immediately invoked function");
})();
js copy
+(function IIFE() {
  console.log("I am an Immediately invoked function");
})();

References


10. Create an IIFE which receives arguments and executes

  • Arguments can be passed in the same way as when calling a regular functions
  • Multiple arguments can be passed similar to function invocation with arguments
js copy
(function IIFE(param1, param2) {
  console.log("I am an Immediately invoked function");
  console.log("Parameter 1: " + param1);
  console.log("Parameter 2: " + typeof param2);
  console.log("Parameter 2 output: " + param2());
})("hello", function () {
  return "I am a string from a function passed to IIFE";
});

Notes

A string and a function is passed as arguments to the IIFE


11. Show the usage of IIFE to set a value of a variable

  • IIFE can be directly executed when it is used as an expression against assignment to a variable
js copy
var randomNumber = (function () {
  return Math.floor(Math.random() * 100);
})();

12. Write a function which can return multiple values from a function

  • In general functions are designed to return a single value.
  • Generators are a special type of functions which return an iterator which in turn can be used to send & receive values.
js copy
function multipleValueReturnFunc() {
  const a = 5,
    b = 10;
  return [a, b];
}

// driver code
const [x, y] = multipleValueReturnFunc();
js copy
function multipleValueReturnFunc() {
  const a = "Java",
    b = "Script";
  return {
    a,
    b,
  };
}

// driver code
const { a: x, b: y } = multipleValueReturnFunc(); // x will have 'Java' and y will have 'Script'
const { a, b } = multipleValueReturnFunc(); // a and b will have respective values
js copy
function* multipleValueReturnFunc() {
  const a = 5,
    b = 10;
  yield a;
  yield b;
}

// driver code
const iterator = multipleValueReturnFunc();
const x = iterator.next().value;
const y = iterator.next().value;

Notes

Array and object are used in the programs to contain multiple values


13. Write a function which can set default values to the parameters of function when an argument is not passed. Also show how to use existing parameters to set the value of another parameter

  • Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed
js copy
function defaultValueFunc(
  num = 10,
  num2 = 20,
  bool = false,
  sum = num + num2,
  string = "Hello"
) {
  console.log(num, string, bool, sum);
}

// driver code
defaultValueFunc(); //  10, 'Hello', false, 30
defaultValueFunc(4, 8); //  4, 'Hello', false, 12
defaultValueFunc(10, 4, true); //  10, 'Hello', true, 14
defaultValueFunc(5, 6, false, 11); //  5, 'Hello', false, 11
defaultValueFunc(undefined, undefined, false); //  10, 'Hello', false, 30

Notes

The default values are set only for missing or undefined. null and other falsy values are considered as valid arguments and default will not be set

References


14. Show the usage of call, apply and bind with practical example

  • 'call' is a method on function prototype and is used to set the context of the function by passing it as 1st argument followed by the arguments
  • 'apply' is a method on function prototype and is used to set the context of the function by passing it as 1st argument followed by the array of arguments
  • 'bind' is a method on function prototype and is used to create a new function with the context as the 1st argument followed by the arguments
js copy
function displayThisValue(param1, param2) {
  console.log(this.value, param1, param2);
}

const obj = {
  value: 10,
};
const valueArr = [20, 30];

// No context set
displayThisValue(20, 30); // undefined, 20, 30

// 'obj' is set as the context using 'call'
displayThisValue.call(obj, ...valueArr); // 10, 20, 30

// 'obj' is set as the context using 'apply'
displayThisValue.apply(obj, valueArr); // 10, 20, 30

// No context set
setTimeout(displayThisValue, 1000, ...valueArr); // undefined, 20, 30

// 'obj' is set as the context using 'bind'
setTimeout(displayThisValue.bind(obj), 1000, ...valueArr); // 10, 20, 30
setTimeout(displayThisValue.bind(obj, ...valueArr), 1000); // 10, 20, 30

Notes

The context inside the function can be accessed using this keyword

References


15. Show the usage of a function which can be used as a constructor

  • A function can be used like a constructor by calling it with the new keyword
  • A constructor function is a normal function but generally used to create an object and may also have functions in its prototype
  • A constructor function is generally preferred to start with a Uppercase letter which is not mandatory
  • The return from the constructor function is a new object created which is accessed with this inside the function
  • Constructor function can return an explicit object as well
js copy
function Employee(id) {
  this.id = id;
}

Employee.prototype.setSalary = function (salary) {
  this.salary = salary;
};

Employee.prototype.getSalary = function () {
  return this.salary;
};

// driver code
const emp = new Employee(1);
emp.setSalary(10000);
console.log(emp.getSalary());

Notes

Constructor function can be called without new keyword as well, which executes the function normally which is of not much use in most of the cases.

References


16. Show the procedure of creating an object using a factory function

  • Any function which is not a class or constructor that returns an object without a new keyword is known as a factory function
  • A normal function which can be modified to return an object which can be called by passing arguments
js copy
function factoryFunc(username, password, isActive = false, isAdmin = false) {
  if (typeof username !== "string" && typeof password !== "string")
    throw new Error("Invalid username or password");

  return {
    username,
    password,
    isActive,
    isAdmin,
    created: new Date(),
  };
}

// driver code
const user = factoryFunc("admin", "password");

References


17. Achieve prototypal inheritance using functions to create objects in JavaScript

  • 2 functions can be used to create objects with constructor call to the functions
  • The prototype of the child function is connected with the parent function to achieve the inheritance behavior
js copy
function parent(name) {
  this.name = name;
}

parent.prototype.getName = function () {
  return this.name;
};

function child(name) {
  parent.call(this, name);
}

child.prototype = Object.create(parent.prototype);
child.prototype.getMyName = function () {
  return this.name;
};

// driver code
var fk = new child("FK");
console.log(fk.getName());
console.log(fk.getMyName());

var pk = new parent("PK");
console.log(pk.getName());

Notes

The solution is one of the known ways of achieving prototypal inheritance, but it is not the only way to achieve it.

References


18. Write a code to show the differences between the techniques, currying and partial application

  • A function returning another function that might return another function, but every returned function must take only one parameter at a time is currying
  • A function returning another function that might return another function, but each returned function can take several parameters is partial application
js copy
// currying
function multiply(num1) {
  return function (num2) {
    return function (num3) {
      return num1 * num2 * num3;
    };
  };
}
js copy
// partial application
function multiply(num1) {
  return function (num2, num3) {
    return function (num4) {
      return num1 * num2 * num3 * num4;
    };
  };
}

References


19. Write a function to copy functions of an object to another object (mixin)

  • Mixins are a form of object composition, where component features get mixed into a composite object
  • In JavaScript we can only inherit from a single object. Mixins allow copying properties of other function prototype or objects to the target object
js copy
// mixin using Object.assign

function mixin(sourceObj, targetObj) {
  // copy properties of source object to target object
  return Object.assign(targetObj, sourceObj);
}

// driver code
const obj1 = {
  task1() {
    console.log("Task1");
  },
};

const obj2 = {
  task2() {
    console.log("Task2");
  },
};

let mixinObj = mixin(obj1, {});
mixinObj = mixin(obj2, mixinObj);
mixinObj.task1(); // Task1
mixinObj.task2(); // Task2
js copy
// mixin using property copy through loops (pre ES6)

function mixin(sourceObj, targetObj) {
  for (var key in sourceObj) {
    // only copy if not already present
    if (!(key in targetObj)) {
      targetObj[key] = sourceObj[key];
    }
  }
  return targetObj;
}

// driver code
var obj1 = {
  task1() {
    console.log("Task1");
  },
};

var obj2 = {
  task2() {
    console.log("Task2");
  },
};

var mixinObj = mixin(obj1, {});
mixinObj = mixin(obj2, mixinObj);
mixinObj.task1(); // Task1
mixinObj.task2(); // Task2

Notes

'task1' and 'task2' from 'obj1' and 'obj2' are copied to 'mixinObj'

References


20. Show the usage Proxy for function

  • The Proxy object enables create a proxy for a function, which can intercept the function calls
  • Proxy takes 1st argument as an function and 2nd argument as a object with different function traps
js copy
const proxy = new Proxy(
  function () {
    console.log(arguments);
  },
  {
    apply(target, context, args) {
      console.log(
        "Proxy apply is invoked on target with context: " +
          context +
          ", arguments: " +
          args
      );
      return target.apply(context, args);
    },
  }
);

// driver code
proxy(1, 2, 3); // Proxy apply is invoked on target with context: undefined, arguments: 1,2,3
proxy.call({}, 1, 2); // Proxy apply is invoked on target with context: [object Object], arguments: 1,2,3
proxy.apply({}, [5, 10]); // Proxy apply is invoked on target with context: [object Object], arguments: 5,10

References


File: web/src/app/concepts/objects/page.mdx

export const metadata = {
title: "Objects | Concepts"
}

1. Show the different ways of creating an object

  • Object can be created using Object constructor
  • Object can also be created using Object literal form
  • Object can be created using new keyword to constructor function
  • Object can be created using Class
js copy
const object = Object.create({ key: value });
js copy
const object = {
  key: value,
};
js copy
function getObject(key, value) {
  this[key] = value;
}

const object = new getObject("key", "value");
js copy
class Obj {
  constructor(key, value) {
    this[key] = value;
  }
}

const object = new Obj("key", "value");

References


2. Display all the keys of an object

  • The keys of an object can be obtained using Object.keys
js copy
for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key);
  }
}
js copy
for (let key of Object.keys(obj)) {
  if (obj.hasOwnProperty(key)) {
    console.log(key);
  }
}
js copy
Object.keys(obj).forEach((key) => {
  if (obj.hasOwnProperty(key)) {
    console.log(key);
  }
});

Notes

obj.hasOwnProperty(key) is used to only display the properties present on the object and not inherited ones.

References


3. Display all the values of an object

  • The values of an object can be obtained using Object.values which returns an array of values
js copy
console.log(Object.values(obj));
js copy
for (let value of Object.values(obj)) {
  console.log(value);
}
js copy
Object.values(obj).forEach((value) => console.log(value));
js copy
for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(obj[key]);
  }
}

Notes

Object.values will only fetch the values of the object and not inherited ones

References


4. Write a function which can check if a given object is empty or not

  • Object is empty if it has no keys
  • Few objects such as Date object does not have any keys but still are not empty. Hence additional check can be implemented to verify the stringification of the object is also empty
js copy
function isObjectEmpty(obj) {
  if (obj !== null && typeof obj !== "undefined" && typeof obj === "object")
    return Object.keys(obj).length === 0 && JSON.stringify(obj) === "{}";
  else return false;
}

Notes

obj.constructor === Object is also used to verify along with the length of keys to check if object is empty which works for objects created with literal form

References


5. Create an empty object which has no prototype attached to it

  • Objects created in JavaScript will have a prototype object on it connected to other object or Object
  • Object constructor can be used to create such an empty object
js copy
const obj = Object.create(null);

References


6. Show the usage of 'Object.entries' to create an object from key value pairs

  • The key value pairs can be directly converted to object using entries method of Object
js copy
const arr = [
  ["0", "a"],
  ["1", "b"],
  ["2", "c"],
];
const obj = Object.fromEntries(arr);
js copy
const map = new Map([
  ["foo", "bar"],
  ["baz", 42],
]);
const obj = Object.fromEntries(map);

References


7. Connect 2 objects so that one object is prototypically connected to the other

  • Objects in JavaScript are connected its prototype and is accessible for objects getPrototypeOf or __proto__
  • setPrototypeOf is used to set the prototype of the object
js copy
const obj1 = { a: 1 };
const obj2 = { b: 2 };
obj2.setPrototypeOf(obj1);
js copy
const obj1 = { a: "Object 1 value" };
const obj2 = { b: "Object 2 value" };
obj2.__proto__ = obj1;

Notes

The lookup happens at the object level initially and if the key is not found, prototype chain lookup happens

References


8. Create an object with getter and setter for property

  • getter and setter on the properties of object can be used to control the read and write behavior
js copy
const obj = {};

Object.defineProperty(obj, "data", {
  _data: 0, // closure variable to hold the data
  get() {
    return this._data;
  },
  set(value) {
    this._data = value;
  },
});

Notes

If the this.data is accessed directly, the function will call itself infinitely. Hence, we would require one more variable to store the data

References


9. Show the different types of accessor properties available for object property and write a code defining them

  • value accessor is used to set the value of the property
  • writable accessor is used to set if the property can be modified or not
  • configurable accessor is used to set the property to be configurable or not
  • enumerable accessor is to set the property to be considered in enumeration
js copy
var obj = {};

Object.defineProperty(obj, "prop", {
  value: 1,
  writable: true,
  configurable: true,
  enumerable: true,
});

Notes

Except value, other accessor mentioned accept true or false

References


10. Show the different options available to prevent the modifications to the object

  • preventExtensions is an Object method which prevents addition of any new property to an object
  • seal is an Object method which prevents addition and deletion of any property in an object
  • freeze is an Object method which prevents addition, deletion and update of any property of an object
  • There are also methods isExtensible, isSealed and isFrozen on Object to check
js copy
Object.preventExtensions(obj);
Object.isExtensible(obj); // false
js copy
Object.seal(obj);
Object.isSealed(obj); // true
js copy
Object.freeze(obj);
Object.isFrozen(obj); // true

References


11. Modify the given object so that it can be used inside a for...of loop

  • Symbol.iterator can be used to define the iterator on the object
  • The values of the object can accessed with for..of the way we can do it for array
js copy
const obj = {
  [Symbol.iterator]() {
    const keys = Object.keys(this);
    let idx = 0;
    return {
      next: () => {
        if (idx >= keys.length) return { value: this[keys[idx++]], done: true };
        else return { value: this[keys[idx++]], done: false };
      },
    };
  },

  key1: "value1",
  key2: "value2",
  key3: "value3",
};
js copy
const obj = {
  *[Symbol.iterator]() {
    for (let key in obj) {
      yield obj[key];
    }
  },

  key1: "value1",
  key2: "value2",
  key3: "value3",
};

References


12. Show the creation of Regular Expression in JavaScript

  • Regular expressions are patterns used to match character combinations in strings
  • Regular expressions can be created using literal form or constructor form
  • Constructor form accepts regular expression as the first argument and flags as the 2nd argument
  • Literal form is simple which takes regular expression and flags in a single expression
js copy
// literal form
let re = /ab+c/g;
js copy
// constructor form
let re = new RegExp("ab+c", "g");

Notes

In JavaScript, regular expressions are objects

References


13. Write a polyfill for Object.create

  • The creating of object can happen by making constructor call to the function
js copy
if (typeof Object.create !== "function") {
  Object.create = function (proto, propertiesObject) {
    if (
      (typeof proto === "object" || typeof proto === "function") &&
      typeof propertiesObject !== "undefined"
    ) {
      // F is a dummy empty function
      function F() {}
      F.prototype = proto;
      return new F();
    } else {
      throw new TypeError("Invalid proto or properties object");
    }
  };
}

References


14. Write a code show Optional chaining for objects and functions

  • The optional chaining operator (?.) permits reading the value of a property located deep within a chain of connected objects
  • The expression short-circuits with a return value of undefined in the absence of property
js copy
// object property access
obj.val?.prop;

// object property access through bracket notation
obj.val?.[expr];

// array index access
obj.arr?.[index];

// object property access for function call
obj.func?.(args);

References


15. Show the usage of static variable & function in a class and accessing it from the code

  • Static members of the class are class level variables and not created for each instances of the class
  • Static members can be accessed directly using class name
js copy
class Browser {
  static className = "Browser";

  constructor(os, browserName) {
    this.os = os;
    this.browserName = browserName;
  }

  static areTheySameBrowsers(browser1, browser2) {
    return browser1.browserName === browser2.browserName;
  }
}

// driver code
const browser1 = new Browser("Linux", "Chrome");
const browser2 = new Browser("Windows", "Firefox");

Browser.className; // Browser
Browser.areTheySameBrowsers(browser1, browser2); // false

References


16. Write a class which uses private variable and function

  • Private members of the class are only accessible within the class and instances of the class do not have access to it
  • Private members can be created with the prefix '#' before the name of the class member
js copy
class ClassWithPrivateFields {
  #privateVar;
  publicVar;

  #privatFunc() {
    this.#privateVar = 7;
    this.publicVar = 10;
  }

  publicFunc() {
    this.#privatFunc();
    return [this.#privateVar, this.publicVar];
  }
}

// driver code
const instance = new ClassWithPrivateFields();

// can't access private variable
instance.privateVar; // undefined

// can't access private function
instance.privatFunc(); // Error
instance.publicFunc(); // 7, 10

17. Show how inheritance works in Class and the use of super keyword with working example

  • Class level inheritance can happen when a class inherits from another class using the keyword extends
  • The child class can access parent class members using the keyword super
  • The non private members of parent class become available to child class when inherited
js copy
class BaseComponent {
  constructor(componentName) {
    this.componentName = componentName;
  }

  setState(obj) {
    this.state = obj;
    this.render();
  }

  addValues(props) {
    return props.reduce((a, b) => a + b);
  }
}

class Component extends BaseComponent {
  constructor(name = "", props) {
    super(name); // super() is used to call parent class consturctor
    this.state = { ...props };
  }

  addValues(...props) {
    const sum = super.addValues(props); // super.property is used to access parent class property
    this.setState({ sum, props });
  }

  render() {
    console.log(`Sum of ${this.state.props} is ${this.state.sum}`);
  }
}

// driver code
let component = new Component("UI Component");
component.componentName; // UI Component
component.addValues(3, 5); // Sum of 3,5 is 8
component.addValues(9, -4, 6, 2); // Sum of 9,-4,6,2 is 13

Notes

super call to constructor within constructor of child class must be the first statement

References


18. Show the way of using Proxy for object

  • The Proxy object enables create a proxy for another object, which can intercept and redefine fundamental operations for that object
  • Proxy can be set for objects (including functions and arrays) to intercept the values which gives us the control on access and modification of the real object
  • Proxy takes 1st argument as an object / function and 2nd argument as a object with different function traps
js copy
let obj = {
  key: "value",
};

let proxy = new Proxy(obj, {
  get(target, handler) {
    console.log("Proxy get is invoked on target with property: " + handler);
    return target[handler];
  },
  set(target, handler, value) {
    console.log(
      "Proxy set is invoked on target object with property: " +
        handler +
        " and value: " +
        value
    );
    target[handler] = value;
  },
});

// driver code
proxy.key2 = "value2"; // Proxy set is invoked on target object with property: key2 and value: value2
proxy.key1; // Proxy get is invoked on target with property: key1

Notes

There are lot of other traps used in Proxy apart from get, set, apply

References


19. Show how can we use for..of loop to iterate on a range with given start and end values in an object

js copy
// Example
let range = {
  start: 1,
  end: 10,
};

for (let i of range) console.log(i); // 1 2 3 4 5 6 7 8 9 10
  • For..of loop uses iterator of an object to fetch the values one at a time
  • Defining an iterator Symbol on the object to iterate from start to end will fetch the values of the range
js copy
Object.defineProperty(range, Symbol.iterator, {
  value: function () {
    let i = this.start;
    return {
      next: () =>
        i <= this.end
          ? { value: i++, done: false }
          : { value: undefined, done: true },
    };
  },
});

20. Prove that private looking variable in a function is not really private specific to that object

  • Private looking variables can be created in a function and can given access by providing function interfaces
  • The functions maintain a closure over function variables and hence the function variables persist inside the function interfaces
  • Though the variable is private within the function and cannot be accessed, these variables are not private to the created object
js copy
function ObjectCreator() {
  var privateVar = 0;

  // function interfaces get, set
  this.getPrivateVar = function () {
    return privateVar;
  };
  this.setPrivateVar = function (value) {
    privateVar = value;
  };
}

// driver code
var obj = new ObjectCreator();
obj.setPrivateVar(10);
obj.getPrivateVar(); // 10

var privateVarAccessor = {
  get: obj.getPrivateVar,
  set: obj.setPrivateVar,
};

// obj private variable is accessible by other external entities
privateVarAccessor.set(5);
privateVarAccessor.get(); // 5
obj.getPrivateVar(); // 10

File: web/src/app/concepts/primitives/page.mdx

export const metadata = {
title: "Primitives | Concepts",
}

1. Show the usage of `typeof` operator on different types of values

  • The typeof operator returns a string indicating the type of the operand
js copy
typeof 50; //   "number"
typeof "text"; //   "string"
typeof true; //   "boolean"
typeof undefined; //   "undefined"
typeof function () {}; //   "function"
typeof 10n; //   "bigint"
typeof Symbol(); //   "symbol"
typeof [1, 2]; //   "object"
typeof {}; //   "object"

typeof NaN; //   "number"        (NaN is Not a Number)
typeof undeclaredVar; //   "undefined"     (undeclaredVariable is never declared)
typeof Infinity; //   "number"        (Infinity, -Infinity, -0 are all valid numbers in JavaScript)
typeof null; //   "object"        (This stands since the beginning of JavaScript)
typeof /regex/; //   "object"        (regular expressions start and end with '/' in literal form)

Notes

Arrays and functions are sub type of objects

References


2. Show the different ways of concatenating numbers and strings

  • Concatenation of strings and numbers is a common practical use case
js copy
// numbers and strings
1 + "2"; // 12
1 + 2 + "3"; // 33
1 + 2 + "3" + "4"; // 334
1 + "One"; // 1One

// strings and numbers
"1" + 2; // 12
"1" + "2" + 3; // 123
"1" + "2" + 3 + 4; // 1234
"1" + "2" + (3 + 4); // 127
"One" + 1; // One1

// mix of string and numbers
1 + 2 + "3" + "4" + 5 + 6; // 33456
1 + 2 + "3" + "4" + (5 + 6); // 33411
"1" + "2" + (3 + 4) + 5 + "6"; // 12756

References


3. Show the conversion from number to string and vice versa

  • Conversion between numbers and strings is a common practical use case
js copy
// number to string conversion
const num = 12;

String(num); // "12"
num.toString(); // "12"
num + ""; // "12"
js copy
// string to number conversion
const str = "12";

Number(str); // 12
+str; // 12
parseInt(str); // 12

Notes

If the number is floating, parseFloat can be used. parseInt and parseFloat are the methods present on the Number object also

References


4. Write a code to operate on integer numbers outside the range of numbers in JavaScript

  • BigInt is a datatype in JavaScript which facilitates the mathematical operations on huge value of integer number
  • It is represented by a suffix 'n' for number value
js copy
// assignment of big integers
const bigNum1 = 1526688934595n,
  bigNum2 = 256489246848n,
  num3 = 1562365;

const bigSum = bigNum1 + bigNum2;
const bigDiff = bigNum1 - bigNum2;
const total = bigNum1 + bigNum2 + BigInt(num3);

Notes

The big integers cannot be operated directly with normal number datatype. 10n + 20 is not allowed

References


5. Show the usage of `||`, `&&`, `??` and `!!` with code examples

  • The logical OR (||) operator for a set of operands is true if and only if one or more of its operands is true
  • The logical AND (&&) operator for a set of operands is true if and only if all of its operands are true
  • The nullish coalescing operator (??) is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand
  • The double NOT (!!) operator used to explicitly force the conversion of any value to the corresponding boolean primitive
js copy
const num1 = 10,
  num2 = 20;

true || false; // true
false || false; // false
false || num1; // 10
0 || num2; // 20
"text" || true; // "text"
num1 > 0 || num2 < 0; // true
js copy
const num1 = 10,
  num2 = 20;

true && true; // true
true && false; // false
true && num1; // 10
num1 && num2; // 20
"text" && num1 + num2; // 30
num1 > 0 && num2 < 0; // false
js copy
undefined ?? 10; // 10
null ?? 20; // 20
false ?? num1; // false
0 ?? num2; // 0
js copy
!!10; // true
!!{}; // true
!!""; // false
!!0; // false

Notes

It is not possible to combine both the AND (&&) and OR operators (||) directly with ??

References


6. Show the frequently and commonly used methods available on `Number` object with coding examples

  • isInteger is used to check if the given number is integer or not
  • parseInt is used to convert a given value in to integer
  • parseFloat is used to convert a given value in to floating number
  • isNaN is used to check if the given value is NaN or no
  • toFixed is used to limit the number of digits after the decimal place
  • toPrecision is used to limit the total number of digits to represent the number
js copy
Number.isInteger(1.5); // false
Number.isInteger(-15); // true

Number.parseInt("5.8"); // 5
Number.parseInt("123x"); // 123

Number.parseFloat("5.86"); // 5.86
Number.parseFloat("-12.69x"); // -12.69

Number.isNaN(NaN); // true
Number.isNaN("text" - 10); // true
Number.isNaN("text"); // false
js copy
(56.369).toFixed(2); // 56.37
(59).toFixed(3); // 59.000

(32.458).toPrecision("3"); // 32.5
(98.1).toPrecision(1); // 1e+2

Notes

NaN is special type of number and this value is results by the invalid mathematical operations such as substraction of number and text

References


7. Write the polyfill for `Number.isNaN`

  • A polyfill is a piece of code used to provide modern functionality on older browsers that do not natively support it
  • NaN is the only value which is not equal to itself and hence comparision operator cannot be used directly to check if a value is NaN
js copy
Number.isNaN =
  Number.isNaN ||
  function isNaN(input) {
    return typeof input === "number" && input !== input;
  };

Notes

Even though the name says Not a Number, it is of type "number"

References


8. Show the frequently and commonly used methods available on `Math` object with coding examples

  • abs is used to get the absolute value of the given number
  • floor is used to get the greatest integer smaller than or equal to the given number
  • ceil is used to get the smallest integer greater than or equal to the given number
  • round is used to round the given number to the nearest integer.
  • max is used to get the largest of zero or more numbers
  • min is used to get the smallest of zero or more numbers
  • sqrt is used to calculate the square root of the given number
  • pow is used to calculate the power base on inputs
  • trunc is used to return the integer part of a number by removing any fractional digits (method is present on prototype of Number)
js copy
Math.abs(-5));                      // 5
Math.floor(1.6));                   // 1
Math.ceil(2.4));                    // 3
Math.round(3.8));                   // 4
Math.max(-4, 5, 6));                // 6
Math.min(-7, -2, 3));               // -7
Math.sqrt(64));                     // 8
Math.pow(5, 3));                    // 125
Math.trunc(-6.3));                  // -6

References


9. How can we solve the problem of comparision of 0.1 + 0.2 with 0.3 where `===` operator fails

  • The addition of 0.1 and 0.2 will result in to 0.30000000000000004 and the comparision with 0.3 fails
  • Number.epsilon is 2-52, which can be used to verify if this decimal values are matching
js copy
0.1 + 0.2 - 0.3 < Number.EPSILON; // true

References


10. Write a code to iterate over a string

  • String can be traversed using its string index or value as string can act like an iterable
js copy
for (let i = 0; i < str.length; i++) {
  console.log(str.charAt(i));
}
js copy
for (let index in str) {
  console.log(str[index]);
}
js copy
for (let value of str) {
  console.log(value);
}
js copy
[...str].forEach((value) => console.log(value));

References


11. Show the usage of template literals with expression interpolation and tagged templates

  • Template literals are string literals allowing embedded expressions and support multi lines
  • Template literals are enclosed by the backtick `
  • Tagged templates allow to parse template literals with a function which gets array of strings and expressions as arguments
js copy
// Template literals with expression interpolation
const num1 = 10,
  num2 = 20;
`The sum of ${num1} and ${num2} is ${num1 + num2}`; // The sum of 10 and 20 is 30
js copy
// Tagged templates
let person = "John";
let membership = [1, 3];

function myTag(strings, person, membership) {
  let communities = ["Java", "JavaScript", "TypeScript", "HTML", "CSS"];

  let str0 = strings[0]; // "Note:"
  let str1 = strings[1]; // "is a member of following communities:"

  let personCommunities = membership.map((index) => communities[index]);
  return `${str0}${person}${str1}${personCommunities}`;
}

myTag`Note: ${person} is a member of following communities: ${membership}`; // Note: John is a member of following communities: JavaScript,HTML

References


12. Write a code to show the working of `try...catch...finally`

  • The try statement consists of a try-block, which contains one or more statements. At least one catch-block, or a finally-block, must be present
  • The exceptions and errors from try block are caught in catch block
js copy
try {
  // Below statement will throw an Error
  callAPI();
} catch (error) {
  // Create a new error and throw
  throw new Error(error); // ReferenceError: callAPI is not defined
} finally {
  console.log("I will execute no matter what happened in try or catch");
}

Notes

  • try can be chained with catch block or finally block
  • try..catch only works synchronously and for runtime errors

References


13. Show the creation and usage of `symbol` with code

  • A "symbol" represents a unique identifier
  • Symbol.for method searches for existing symbols in a runtime-wide symbol registry returns the same. If not found, creates a new Symbol
  • Symbol.keyFor method retrieves the name of the symbol
js copy
// new symbol
let symId = Symbol("id");

// global symbol
let symUsername = Symbol.for("username");

// get name by symbol
Symbol.keyFor(symUsername); // username

Notes

Symbols are skipped by for…in

References


14. Demonstrate the usage of String Escape Sequences

  • Specifies that the following character should be interpreted as a literal character
js copy
// 1. Newline and Tab
const newlineTabExample = "Line 1\nLine 2\tTabbed";
console.log(newlineTabExample);
// Output:
// Line 1
// Line 2    Tabbed

// 2. Escaping Double Quotes
const escapeDoubleQuoteExample = "He said, \"Hello, World!\"";
console.log(escapeDoubleQuoteExample);
// Output: He said, "Hello, World!"

// 3. Escaping Single Quotes
const escapeSingleQuoteExample = 'It\'s a wonderful day!';
console.log(escapeSingleQuoteExample);
// Output: It's a wonderful day!

// 4. Unicode Smiley Face
const unicodeSmileyExample = "Smile: \u263A";
console.log(unicodeSmileyExample);
// Output: Smile: ☺

// 5. File Path with Double Backslashes
const filePathExample = "Path: C:\\\\Program Files\\\\MyApp";
console.log(filePathExample);
// Output: Path: C:\\Program Files\\MyApp

15. Show the usage of instanceof operator on different types of objects

The instanceof operator checks if an object is an instance of a specific class or constructor function.

javascript
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log(function() {} instanceof Function); // true
console.log(new Date() instanceof Date); // true
console.log("text" instanceof String); // false (primitive string, not an object)
console.log(new String("text") instanceof String); // true (String object)

References


16. Demonstrate the usage of Array.isArray() to check for arrays

The Array.isArray() method determines whether the provided value is an array.

javascript
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray("string")); // false
console.log(Array.isArray(new Array())); // true

References


17. Show how to create and use a WeakMap with objects

WeakMaps are collections of key-value pairs where keys are objects and can be garbage-collected if there are no other references.

javascript
const weakMap = new WeakMap();

let obj1 = {};
let obj2 = {};

weakMap.set(obj1, "Object 1");
weakMap.set(obj2, "Object 2");

console.log(weakMap.get(obj1)); // "Object 1"
console.log(weakMap.get(obj2)); // "Object 2"

obj1 = null; // obj1 can be garbage collected now
// weakMap entry for obj1 will also be removed automatically

References



File: web/src/app/concepts/variables/page.mdx

export const metadata = {
title: "Variables | Concepts"
}

1. Create a Variable using var Keyword and log it to the console

  • Variables declared with var can be redeclared within the same scope without causing an error.
js copy
var num = 10;
   console.log(num); // 10

Notes

  • var variables have function scope, meaning they are only accessible within the function they are declared in, or globally if declared outside any function.
  • Declarations with var are hoisted to the top of their scope, but not the initializations.

References


2. Create a Variable using let Keyword and log it to the console

  • Variables declared with let cannot be redeclared within the same scope, which helps prevent accidental redeclarations and errors.
js copy
let Str = "Hello World";
    console.log(Str); // "Hello World"

Notes

  • let variables are hoisted but not initialized, leading to a "temporal dead zone" where the variable cannot be accessed until the declaration is encountered.
  • let variables have block scope, meaning they are only accessible within the block they are declared in (e.g., inside a set of curly braces {}).
  • let is a keyword introduced in ES6 for declaring variables in JavaScript

References


3. Create a constant using const Keyword and log it to the console

  • Variables declared with const cannot be redeclared within the same scope, helping to prevent accidental redeclarations and potential bugs.
js copy
const bool = true;
    console.log(bool); // True

Notes

  • Variables declared with const cannot be reassigned after their initial assignment. However, if the variable is an object or array, its contents can still be modified.
  • const variables have block scope, meaning they are only accessible within the block they are declared in (e.g., inside a set of curly braces {}).

References


4. Make variables with different data types and print their type to the console using typeof method

  • The typeof operator is used to determine the type of a given variable or expression, returning a string indicating the type.
js copy
let number = 10;
    let string = "hello World";
    let boolean = true;
    let object = {
       name: "Chai",
       key: "code"
    };
    let array = ['Fruits', 'Chai', 'Vegetable'];

    console.log(typeof number);  // number
    console.log(typeof string);  // string
    console.log(typeof boolean); // boolean
    console.log(typeof object);  // object
    console.log(typeof array);   // object (arrays are of type object in JavaScript)

Notes

  • It returns common type strings such as 'number', 'string', 'boolean', 'object', 'function', and 'undefined'.
  • Both arrays and objects return 'object', so typeof does not differentiate between them directly.

References


5. Declare a variable using let Keyword and assign it a value and reassign its value

  • Variables declared with let can be reassigned new values after their initial declaration.
js copy
let a = "Hello World";
    console.log(a); // "Hello World"
    a = "Hello World 2";
    console.log(a); // "Hello World 2"

Notes

  • Reassignment is subject to the variable's block scope; it can only be reassigned within the same block.
  • While reassignment is allowed, let variables cannot be redeclared in the same scope.

References


6: Make a constant using const Keyword and try to reassign the value and Identify the error

  • Variables declared with const cannot be reassigned a new value after their initial assignment.
js copy
const a = "js Concepts";
    console.log(a); // "js Concepts"
    a = "JS Concepts & Challenges"; // This line will cause an error

Notes

  • The const keyword provides a constant reference to a value, but for objects and arrays, the contents (properties/elements) can still be modified.
  • Like let, const variables have block scope, meaning they are only accessible within the block they are declared in.

References


7. Demonstrate Hoisting with var

Show how var is hoisted to the top of its scope.

javascript
console.log(myVar); // undefined
var myVar = "Hoisted!";
console.log(myVar); // "Hoisted!"

Notes

  • Variable declarations with var are hoisted to the top of their scope, but their initializations are not.

References


8. Create a Function to Demonstrate Scope of let

Demonstrate the difference between block scope and function scope using let.

javascript
function testScope() {
    let x = "I'm inside the function";
    if (true) {
        let y = "I'm inside the block";
        console.log(y); // "I'm inside the block"
    }
    // console.log(y); // Uncaught ReferenceError: y is not defined
    console.log(x); // "I'm inside the function"
}
testScope();

Notes

  • This example illustrates how let is scoped to the nearest enclosing block, preventing access outside of it.

References


9. Create Variables with Object and Array and Log Their Types

Show how to create and log an object and an array's type.

javascript
let user = {
    name: "Alice",
    age: 30
};
let colors = ["red", "green", "blue"];

console.log(typeof user); // "object"
console.log(typeof colors); // "object" (arrays are objects)

Notes

  • Both arrays and objects are identified as "object" type in JavaScript.

References



File: web/src/app/interview_questions/page.mdx

1. Explain the concepts of call, apply, and bind in JavaScript. Provide examples.

Description: call, apply, and bind are methods used to change the this value in functions.

javascript
const person = { name: 'Alice' };

 function greet(greeting) {
   console.log(`${greeting}, ${this.name}!`);
 }

 greet.call(person, 'Hello'); // Output: Hello, Alice!
 greet.apply(person, ['Hi']); // Output: Hi, Alice!

 const greetBound = greet.bind(person);
 greetBound('Hey'); // Output: Hey, Alice!

2. Explain the difference between `let`, `const`, and `var` in JavaScript.

text
In JavaScript, `let`, `const`, and `var` are used to declare variables. Each has different scoping rules and reassignment capabilities, making them suitable for different use cases.

  #### 1. **`var`**:
    - `var` was traditionally used to declare variables in JavaScript.
    - Variables declared with `var` are function-scoped, meaning they are only accessible within the function they are declared in.
    - Variables declared with `var` can be redeclared and updated.

    ```javascript
    function exampleVar() {
      var x = 10;
      if (true) {
        var x = 20;  // This reassigns the existing variable 'x'
        console.log(x);  // Output: 20
      }
      console.log(x);  // Output: 20 (not 10)
    }
    ```

  #### 2. **`let`**:
    - Introduced in ES6, `let` allows block-scoping of variables, making them accessible only within the block they are defined in (e.g., if, for, while blocks).
    - Variables declared with `let` can be reassigned but cannot be redeclared in the same scope.

    ```javascript
    function exampleLet() {
      let y = 30;
      if (true) {
        let y = 40;  // This creates a new block-scoped variable 'y'
        console.log(y);  // Output: 40
      }
      console.log(y);  // Output: 30 (not affected by the inner 'y')
    }
    ```

  #### 3. **`const`**:
    - Also introduced in ES6, `const` is used to declare constants whose values cannot be reassigned.
    - Variables declared with `const` are block-scoped like `let`.
    - A `const` variable must be assigned a value during declaration and cannot be left uninitialized.

    ```javascript
    function exampleConst() {
      const z = 50;
      // z = 60;  // Error: Assignment to a constant variable
      console.log(z);  // Output: 50
    }
    ```

  In summary:
    - Use `var` for traditional function-scoped variables (but it's recommended to use `let` and `const` in modern JavaScript).
    - Use `let` when you need to reassign a variable's value within the same block.
    - Use `const` when you want to define a constant value that should not be reassigned.

    It's good practice to use `let` and `const` over `var` for better scoping and to avoid potential issues related to hoisting and unintended variable reassignment.

3. What is a closure in JavaScript? Provide an example.

Answer:

javascript
function outer() {
  const message = 'Hello';
  function inner() {
    console.log(message);
  }
  return inner;
}

const innerFunc = outer();
innerFunc();  // Output: 'Hello'

4. What is event delegation in JavaScript?

Answer: Event delegation is a technique where a single event listener is attached to a common ancestor, allowing events to be handled for multiple children.

5. What is the difference between `==` and `===` in JavaScript?

Answer: == checks for equality with type coercion, while === checks for strict equality without type coercion.

6. What is the purpose of the `async` and `await` keywords in JavaScript?

Answer: async and await are features introduced in ES2017 (ES8) that make working with asynchronous code more readable and easier to manage. They are built on top of promises.

text
#### 1. **`async`**:
  - `async` is used to declare that a function will work with promises and may use `await` within its body.
  - It allows a function to return a promise implicitly.
  - Functions marked with `async` always return a promise, even if you return a non-promise value.

  ```javascript
  async function asyncFunction() {
    return 42; // Equivalent to returning Promise.resolve(42)
  }
  ```

#### 2. **`await`**:
  - `await` can only be used within an `async` function.
  - It is used to pause the execution of the function until a promise is resolved or rejected.
  - It "awaits" the result of a promise and returns the resolved value or throws an error for a rejected promise.

  ```javascript
  async function fetchUserData() {
    try {
      const response = await fetch('https://api.example.com/user');
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('Error:', error);
    }
  }
  ```

#### 3. **Difference from `.then()`**:
- While both `await` and `.then()` handle asynchronous operations, the key difference lies in how they manage the flow of asynchronous code.
- `.then()` is used with promises and is chaining-based, where each `.then()` function returns a promise and allows you to chain further operations.
- `await`, on the other hand, allows for more synchronous-like code within `async` functions, making asynchronous code appear more linear and readable.

```javascript
// Using .then()
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// Using await
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}
```
In summary, `async` and `await` make asynchronous code look and behave more like synchronous code, enhancing readability and maintainability, especially when dealing with promises.

7. Explain what the `this` keyword refers to in JavaScript.

Answer:
this refers to the object on which a method is being called.

8. What is a promise in JavaScript? Provide an example of creating and using a promise.

Answer:

javascript
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise resolved!');
  }, 2000);
});

myPromise.then((result) => {
  console.log(result);
}).catch((error) => {
  console.error(error);
});

9. What is a callback function in JavaScript? Provide an example.

Answer:

javascript
function fetchData(callback) {
  setTimeout(() => {
    callback('Data fetched!');
  }, 2000);
}

fetchData((data) => {
  console.log(data);
});

10. What is the difference between `null` and `undefined` in JavaScript?

text
*Answer:*
`null` is an assignment value representing no value or no object, while `undefined` is a primitive value automatically assigned to uninitialized variables.

11. What is event bubbling in JavaScript?

text
*Answer:*
Event bubbling is the propagation of an event from the target element up to its parent and higher ancestors in the DOM tree.

12. What is event.preventDefault()? Provide an example of its usage.

text
*Answer:*
```js
const submitButton = document.getElementById('submitButton');
submitButton.addEventListener('click', event => {
  event.preventDefault(); // Prevents form submission
  console.log('Form submission prevented.');
});
```

13. What are arrow functions in JavaScript? Provide an example.

text
*Answer:*
```javascript
const add = (a, b) => a + b;
console.log(add(2, 3));  // Output: 5
```

14. What is the purpose of the `localStorage` and `sessionStorage` objects in JavaScript?

text
*Answer:*
They provide a way to store key-value pairs in a web browser, with `localStorage` persisting even after the browser is closed and reopened, and `sessionStorage` existing only for the duration of the page session.

15. Explain event handling in JavaScript and provide an example of attaching an event listener.

text
*Answer:*
```javascript
const button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log('Button clicked!');
});
```

16. What is the difference between `map()` and `forEach()` array methods in JavaScript?

text
*Answer:* `map()` returns a new array with the results of a function applied to each element, while `forEach()` only iterates over the array and does not return a new array.

17. What is a RESTful API and how do you make a GET request using JavaScript?

text
*Answer:*
```javascript
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
```

18. What is the purpose of the `use strict` directive in JavaScript?

text
The "use strict" directive in JavaScript is used to enable a stricter interpretation of the code, catching common mistakes and preventing the use of certain error-prone features. When this directive is applied, the JavaScript engine enforces stricter rules for writing code.

#### 1. Purpose:
  - It helps in writing more reliable and maintainable code by identifying and disallowing potentially error-prone behavior.
  - It prevents the accidental creation of global variables by enforcing block scope rules with `let` and `const`.
  - It disallows the use of certain language features that are deprecated or considered bad practice.

#### 2. Example:
  ```javascript
  // Without "use strict"
  function withoutStrict() {
    variable = 10;  // This will create a global variable accidentally
    console.log(variable);
  }

  withoutStrict();  // Output: 10

  // With "use strict"
  function withStrict() {
    'use strict';
    variable = 20;  // This will throw a ReferenceError
    console.log(variable);
  }

  withStrict();  // Error: variable is not defined
  ```

  In the first example without "use strict," `variable` is mistakenly created as a global variable, which can lead to unexpected behavior and bugs in a larger codebase.

  In the second example with "use strict," attempting to assign a value to `variable` without declaring it with `var`, `let`, or `const` will throw a `ReferenceError`, indicating that `variable` is not defined. This helps catch potential bugs and encourages better coding practices.

  To enable "use strict" globally in a script, you can add it at the beginning of your JavaScript file or within a function. For modern JavaScript development, it's recommended to use "use strict" to enhance code quality and reduce the risk of errors.

19. Explain hoisting in JavaScript.

text
*Answer:* 

- Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compile phase.

```js
console.log(x);  // Output: undefined
var x = 10;
console.log(x);  // Output: 10
```

20. How do you handle errors in JavaScript? Provide an example of using a `try...catch` block.

text
*Answer:*
```javascript
try {
  // Code that may throw an error
  const result = 10 / 0;
  console.log(result);
} catch (error) {
  console.error('An error occurred:', error.message);
}
```

21. What are template literals in JavaScript? Provide an example.

Answer:

  • Template literals are a feature introduced in ES6 that allow for easier string interpolation and multi-line strings. They are enclosed by backticks (`) instead of single or double quotes.

    javascript
    const name = 'Alice';
    const greeting = `Hello, ${name}!`;
    console.log(greeting); // Output: Hello, Alice!

22. Explain the concept of "prototypal inheritance" in JavaScript.

Answer:

  • Prototypal inheritance is a feature in JavaScript where objects can inherit properties and methods from other objects. This is achieved through the prototype chain.

    javascript
    const animal = {
      speak() {
        console.log('Animal speaks');
      },
    };
    
    const dog = Object.create(animal);
    dog.speak(); // Output: Animal speaks

23. What are Promise.all() and Promise.race()? Provide examples of their usage.

Answer:

  • Promise.all() takes an array of promises and returns a single promise that resolves when all of the promises in the array have resolved, or rejects if any promise is rejected.

  • Promise.race() returns a promise that resolves or rejects as soon as one of the promises in the array resolves or rejects.

    javascript
    // Example of Promise.all
    Promise.all([
      Promise.resolve(1),
      Promise.resolve(2),
      Promise.resolve(3),
    ]).then(values => {
      console.log(values); // Output: [1, 2, 3]
    });
    
    // Example of Promise.race
    Promise.race([
      new Promise((resolve) => setTimeout(() => resolve('First'), 1000)),
      new Promise((resolve) => setTimeout(() => resolve('Second'), 500)),
    ]).then(result => {
      console.log(result); // Output: 'Second'
    });

24. What are higher-order functions in JavaScript? Provide an example.

Answer:

  • Higher-order functions are functions that take other functions as arguments or return functions as their result. This allows for more abstract and reusable code.
text
```javascript
function createMultiplier(multiplier) {
  return function(x) {
    return x * multiplier;
  };
}

const double = createMultiplier(2);
console.log(double(5)); // Output: 10
```

25. What is the difference between shallow copy and deep copy?

Answer:

  • A shallow copy duplicates the top-level properties of an object. If the properties are references to other objects, the references are copied, not the actual objects.
  • A deep copy creates a new object and recursively copies all properties and their values.
javascript
const original = { a: 1, b: { c: 2 } };

// Shallow copy
const shallowCopy = Object.assign({}, original);
shallowCopy.b.c = 3; // Changes 'c' in both objects
console.log(original.b.c); // Output: 3

// Deep copy
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.b.c = 4; // Changes 'c' only in deepCopy
console.log(original.b.c); // Output: 3

26. What is the purpose of setTimeout and setInterval in JavaScript? Provide examples.

Answer:

  • setTimeout is used to execute a function after a specified delay (in milliseconds).
  • setInterval is used to repeatedly execute a function at specified intervals.
javascript
setTimeout(() => {
  console.log('Executed after 1 second');
}, 1000);

let count = 0;
const intervalId = setInterval(() => {
  console.log('Count:', count++);
  if (count === 5) clearInterval(intervalId); // Stop after 5 counts
  }, 1000);

27. What are the JavaScript data types?

Answer:

  • JavaScript has several data types, including:

  • Primitive Types:

    1. string: Represents text values.
    2. number: Represents numeric values.
    3. boolean: Represents true or false.
    4. null: Represents an intentional absence of any object value.
    5. undefined: Represents a variable that has been declared but not yet assigned a value.
    6. symbol: Represents a unique identifier (introduced in ES6).
    7. bigint: Represents integers with arbitrary precision (introduced in ES11).
  • Reference Types:

    1. object: Represents complex data structures like arrays and objects.

28. What is the difference between synchronous and asynchronous programming in JavaScript?

Answer:

  • Synchronous programming executes code in a sequential manner, where each operation must complete before the next one starts.
  • Asynchronous programming allows for operations to be executed independently of the main program flow, enabling code to run in the background while other operations continue.
javascript
// Synchronous example
console.log('First');
console.log('Second');

// Asynchronous example
setTimeout(() => {
  console.log('Asynchronous operation');
}, 1000);
console.log('Third');

29. How can you check if a variable is an array in JavaScript?

Answer:

  • You can use the Array.isArray() method to check if a variable is an array.
javascript
const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // Output: true

const obj = {};
console.log(Array.isArray(obj)); // Output: false

30. What is the difference between static and dynamic typing in JavaScript?

Answer:

  • Static typing requires variable types to be declared explicitly, enabling type checking at compile time (not supported in
    JavaScript).
  • Dynamic typing allows variables to hold values of any type without explicit type declaration, enabling type checking at runtime.

31. What are the main differences between ES5 and ES6?

  1. Variable Declarations
    ES5: Uses var (function-scoped).
    ES6: Introduces let and const (block-scoped).

  2. Arrow Functions
    ES5: Regular functions with function.
    ES6: Arrow functions (() => {}) with lexical this.

  3. Template Literals
    ES5: String concatenation with +.
    ES6: Template literals using backticks for interpolation.

  4. Destructuring Assignment
    ES5: Manual extraction of values.
    ES6: Simplified destructuring for arrays and objects.

  5. Modules
    ES5: No native support; relies on libraries.
    ES6: Native import and export for modules.

  6. Promises
    ES5: Callbacks for async operations.
    ES6: Promises for better async handling.

  7. Iterators and Generators
    ES5: No support for iterators.
    ES6: Introduces iterators and generator functions.

32. How do you implement inheritance in JavaScript?

Inheritance can be implemented using prototypes or the class syntax introduced in ES6.

javascript
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  console.log(`${this.name} makes a noise.`);
};

function Dog(name) {
  Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
  console.log(`${this.name} barks.`);
};

33. What is a memory leak in JavaScript, and how can you avoid it?

  • A memory leak occurs when memory that is no longer needed is not released. Common causes include global variables, closures, and forgotten timers.
    You can avoid memory leaks by ensuring proper cleanup of unused objects and avoiding unnecessary global variables.


File: .github/FUNDING.yml

These are supported funding model platforms

github: sadanandpai
custom: https://www.buymeacoffee.com/sadanandpai