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:
npm install
npm run dev
# or
yarn
yarn dev
# or
pnpm install
pnpm devOpen 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
setTimeout(
function (text) {
console.log(text);
},
3000,
"Hello, World"
);setTimeout(() => console.log("Hello, World"), 3000);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
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
const num1 = 1,
num2 = 10;
for (let i = num1; i <= num2; i++) {
setTimeout(() => console.log(i), i * 1000);
}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
setIntervalfunction repeats a block of code at every given timing eventclearIntervalis used to stop the setInterval execution
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
var num1 = 10,
num2 = 1;
for (var i = num1; i >= num2; i--) {
setTimeout(console.log, (num1 - i) * 1000, i);
}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
setIntervalcan be used to achieve the task and handle the start & stop of data display
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
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
// 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
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
thenhandlers for all the promises thenmethod on Promise also returns a promise which can be used to performthenon 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
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);
}
);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
awaitfor each promise can be used to execute in sequence
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
thenhandler - The failure handler will receive the error and continue with next execution which will not propagate failures
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-catchblock can be used on async functions catchblock for each asynchronous function can be used to catch errors and continue with next execution which will not propagate failures
(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
reducecan be used to make the sequential execution on promise settlement
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];
asyncFuncArr.reduce((acc, asyncFn) => {
return acc.then(() => asyncFn().then(console.log));
}, Promise.resolve());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
reducecan 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
const asyncFuncArr = [asyncFunc1, asyncFunc2, asyncFunc3];
asyncFuncArr
.map((async) => async())
.reduce((acc, promise) => {
return acc.then(() => promise).then((data) => console.log(data));
}, Promise.resolve());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.raceis 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
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
fetchrequest attempts to make calls after increasing time delay on failure - If all the attempts by to get response fails, promise gets rejected
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
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
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
function mergeArray(arr1, arr2 = arr1) {
return [...arr1, ...arr2];
}function mergeArray(arr1, arr2 = arr1) {
return arr1.concat(...arr2);
}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
slicemethod on array can be used to fetch the values of range in the arraysplicemethod on array can be used to replace the value of range in the array
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
sortmethod 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
arr.sort((a, b) => a - b); // ascending
arr.sort((a, b) => b - a); // descendingNotes
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
// Example
const books = [
{ name: "Harry Potter", author: "Joanne Rowling" },
{ name: "Warcross", author: "Marie Lu" },
{ name: "The Hunger Games", author: "Suzanne Collins" },
];sorttakes 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
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
filteris the method on Array which can be used to filter. It receives a function which can return boolean to filter the elementsmapis 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
const positiveArr = arr.filter((value) => value >= 0);
const squaredPositiveArr = arr.map((value) => value * value);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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
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
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]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
const doesJohnExist = arr.some((obj) => obj.name === "John");const jonhObject = arr.find((obj) => obj.name === "John");
const doesJohnExist = jonhObject ? true : false;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
mapmethod can be used
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
reducemethod of array can be used efficiently to calculate the sum with or without initial value
const sum = arr.reduce((acc, value) => acc + value, 0);const sum = arr.reduce((acc, value) => acc + value);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.maxis a method which returns maximum value from a given list of valuesreducecan also be designed to return the maximum value of each comparision
const max = Math.max(...arr);
arr.indexOf(max); // position of max numberlet max = a[0],
position = 0;
for (let index in arr) {
if (arr[index] > max) {
position = index;
max = value;
}
}
position; // position of max numberconst max = arr.reduce((a, b) => (a > b ? a : b));
arr.indexOf(max); // position of max numberNotes
Though 1st solution is verbose compared to 2nd, but has good performance
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min
11. Find the number of occurences of minimum value in the numbers list
filtermethod can be used to fetch all the minimum values and we can get the count of those values
const min = Math.min(...arr);
minArr = arr.filter((value) => value === min);
minArr.length; // count of minimum value occurences12. Create an array of length n with all the values of it set to 10
fillis a method on Array prototype which fills all the slots of array with the value given passed as the argument
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
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
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)
everyis a method on Array prototype which returns true only if all the elements condition satisfies the condition
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)
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
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
const intersectionArr = arr1.filter((value) => arr2.includes(value));
const distinctIntersectionArr = [...new Set(intersectionArr)];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
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
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
// 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
Setas the 2 objects with same structure and data have different references Mapcan 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
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
settrap
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
// Example
let arr = [10, 20, 30];
arr[-1]; // 30
arr[-2]; // 20gettrap of proxy can be used to map the negative index to the valid array position
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
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
- https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
- https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
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
// 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?
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.
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.
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); // node2Targetconst 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
/**
* @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
/**
* @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
/**
* @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.
/**
* @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
/**
* @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.
/**
* @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.
/**
* @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.
/**
* 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.
/**
* @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:
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:
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.
<!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.
<!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().
<!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.
<!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.
<!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.
<!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.
<!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.
<!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.
<!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.
<!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.
<!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
// 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
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
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(); // 8Notes
'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
bindmethod creates a new function that, when called, has its this keyword set to the provided context
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
bindwith exception that if there is a context set during the execution it will override
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
- https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch2.md#softening-binding
- https://gist.github.com/getify/9043478
5. Write a function which helps to achieve multiply(a)(b) and returns product of a and b
// Example
multiply(2)(4); // 8
multiply(5)(3); // 15- The implementation of this can be achieved by calling a function which returns a function
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
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 applicationReferences
7. Design a function which helps to do debouncing
- The
debouncefunction 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
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
throttlingfunction 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
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
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
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
// 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
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
// 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
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
maporobject) which stores the values of function output against the input
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
// 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
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);
};
};
}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
// 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
function sum(a) {
return function (b) {
if (b === undefined) {
return a;
}
return sum(a + b);
};
}const sum = (a) => (b) => b === undefined ? a : sum(a + b);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
applykeyword in proxy can be used to achieve the functionality without modifying the existing function code
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
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
typeofoperator on value gives the type of value- Recursive solution can be used to iterate over all the nested objects
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
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
delete obj[key];
}
}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
Object.assign({}, obj);{ ...obj};JSON.parse(JSON.stringify(obj));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
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
getterandsetteron the properties of object can be used to control the read and write behavior
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;
},
});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
writabletofalsesets the property to be read only
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
// Example
const obj = {
id: 1,
username: "John",
password: "secret",
email: "[email protected]",
};JSON.stringifyis 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
JSON.stringify(obj, (key, value) => (key === "password" ? undefined : value)); // {"id":1,"username":"John","email":"[email protected]"}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
nextwill return an object which contains value and done properties
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; // trueReferences
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
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
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
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
pushandpopby passing the object context
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
// 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
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
newkeyword followed by classname
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(); // 11000Notes
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
setkeyword using the Proxy
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
// Example
let range = {
start: 10,
end: 50,
};
5 in range; // false
25 in range; // true- The object
incan be trapped using Proxy traphas, to check if the value is in the range or not
range = new Proxy(range, {
has(target, value) {
return value >= target.start && value <= target.end;
},
});16. Write a function that accepts a topic and a list of related tags to store the information. The same function should return all the topics when requested with a tag name
// 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
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
// 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
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
Weaksetcan 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
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
// 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)
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
// Example
var circularReferenceObj = { data: 123 };
circularReferenceObj.myself = circularReferenceObj;- Stringification of an object having circular references will throw an error
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
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());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
gettrap of proxy can be used to create the objects dynamically and set the value
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 valueFile: 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
let num1 = 10, num2 = 20;
[num1, num2] = [num2, num1];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
// 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
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.randomfunction returns a floating-point, pseudo-random number between 0 (inclusive) and 1 (exclusive)
function randomNumberGeneratorInRange(rangeStart, rangeEnd) {
return rangeStart + Math.floor(Math.random() * (rangeEnd - rangeStart + 1))
}
randomNumberGeneratorInRange(10, 50); // 12Notes
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
const str = "JavaScript is awesome";
let reversedString = "";
for (let i = 0; i < str.length; i++) {
reversedString = str.charAt(i) + reversedString;
}
reversedString; // "emosewa si tpircSavaJ"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
const str = "JavaScript is awesome";
str.split(" ").reverse().join(" "); // "awesome is JavaScript"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
let num = 3849;
let reversedNum = 0;
while (num !== 0) {
reversedNum = reversedNum * 10 + (num % 10);
num = Math.floor(num / 10);
}
reversedNum; // 9483let num = 3849;
let numStr = String(num);
+numStr.split("").reverse().join(""); // 94837. 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
replaceAllis the inbuilt String function on prototype which can be used to replace a string with another string
str.split(" ").join("_");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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
8. Write a function which can convert the time input given in 12 hours format to 24 hours format
// 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
endsWithString method - An extra 0 would be needed if the hours have single digit
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'
// 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)"); // 18indexOfandlastIndexOfare 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
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
// 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
substrmethods of String can be used to fetch the part of the string
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
slicemethod of array can be used to get the number of words which will then be joined back
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
// 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
testmethod of regular expression can be used to validate if the mobile number pattern matches or not
function validateMobile(str) {
const regexMobile = /^(\+91|0)?\s?\d{10}$/;
return regexMobile.test(str);
}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
// 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
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
// 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
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
// Example
stringChop("JavaScript"); // ["JavaScript"]
stringChop("JavaScript", 2); // ["Ja", "va", "Sc", "ri", "pt"]
stringChop("JavaScript", 3); // ["Jav", "aSc", "rip", "t"]- String can be chopped using
slicemethod of String - Regular expression can also be used effectively to this operation
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;
}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
replacemethod on String accepts a string or regex as the argument
const str = "I love JavaScript";
str.replace(/[aeiou]/gi, ""); // _lv_JvScrptReferences
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'
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
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"); // 47References
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.
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.
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
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
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)
thenmethod 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
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
setTimeoutto make the code more readable - Function can take delay as argument and return a promise which gets resolved after timeout is complete
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
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
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
AbortControlleris an interface which can be used to abort a fetch requestsignalobject of the AbortController object can be used as the part of the argument tofetchand abort on controller object can be used to stop the request
const controller = new AbortController();
var signal = controller.signal;
fetch(url, { signal })
.then((response) => {
console.log(response);
})
.catch((err) => {
console.warn(err);
});
controller.abort();References
- https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
- https://davidwalsh.name/cancel-fetch
8. Show the working of async await work with promises
asyncfunctions are asynchronous functions in which the asynchronous code can be executed in synchronous looking manner usingawaitawaitexpects 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
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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
- https://javascript.info/async-await
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.allis 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
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));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.allSettledis 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'
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);
});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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
- https://davidwalsh.name/promise-allsettled
11. Explain the working of Promise.race with few asynchronous function example
- The
Promise.racemethod returns a promise that fulfills or rejects as soon as one of the promises fulfills or rejects, with the success or failure
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 keywordfunction - Generator when called returns an
iteratorwhich can be used to callnexton it yieldkeyword can be used inside such a function and stops the execution
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; // 8Notes
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
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
resolveandrejectmethods will have to be passed to the resolver which the user code will ivoke with data once settledsetTimeoutwith zero delay can be used to not immediately execute the resolver- List of callbacks to
thento be invoked can be stores in the array of success and failure list - Once resolved or rejected, promise cannot change the state
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.allmethod is fail fast procedure to return all the promise resolved data in array or failed reason
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
// 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
// literal form
const arr = [];// constructor form
const arr = new Array();// pre defined number of slots
const arr = new Array(10);// with values
const arr = [1, true, "string"];// 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
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}for (let index in arr) {
console.log(arr[index]);
}for (let value of arr) {
console.log(value);
}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
pushmethod of array - Values to the array can be prepended using
unshiftmethod of array
const arr = [2, 3];
arr.push(4); // [2, 3, 4]
arr.unshift(1); // [1, 2, 3, 4]const arr = [3, 4];
arr.push(5, 6); // [3, 4, 5, 6]
arr.unshift(1, 2); // [1, 2, 3, 4, 5, 6]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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
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
splicemethod of array - Values of the array can also be inserted to any position using
splicemethod of array - 2nd argument is passed as 0 which inserts the elements without replacing
- The values passed after 2nd argument are considered for insertion
const arr = [1, 2, 2, 3];
const position = 2;
const count = 1;
arr.splice(position, count); // [2]
console.log(arr); // [1, 2, 3]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
lengthof the array to 0 will automatically makes the array empty popandshiftoperation on array can also be used to empty the array where each elements get removed
arr = [];arr = new Array();arr.length = 0;while (arr.length > 0) {
arr.pop();
}while (arr.length > 0) {
arr.shift();
}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.isArrayis a method which checks if the given argument is an array or not- Alternatively the
toStringmethod present on Object prototype can be used to check if it is an array
Array.isArray(arr);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
pushandpopoperations - Queue is a 'First In First Out' data structure can be achieved using
pushandshiftoperations
// To add the value to the stack
arr.push(value);
// To remove the value from the stack
arr.pop();// 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
undefinedvalue present inside array - Holes do not get iterated in
filterwhich will just fetch all the values exceptundefined
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
// 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
// Example1
// browser === "chrome" || browser === "firefox" || browser === "IE" || browser === "safari"
const browserList = ["chrome", "firefox", "IE", "safari"];
browserList.includes(browser);// 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
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}for (let rowArr of arr) {
for (let value of rowArr) {
console.log(value);
}
}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
const set = new Set();
set.add(1);
set.add(true);
set.add("text");
set.add(1);
set; // 1, true, "text"const set = new Set([1, 2, 3]);
set; // 1, 2, 3References
12. Write a program to store values in to a map
Mapholds key-value pairs and remembers the original insertion order of the keysMapcan be created empty & then added with values or can be initialized also with key-value pairs
const map = new Map();
map.set(1, 1000);
map.set(true, false);
map.set("text", "String");
map; // [1, 1000] [true, false] ["text", "String"]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
setis an iterable object and can be iterated using for..of loopsetcan also be iterated by simpleforEachloop
for (let val of set) console.log(val);set.forEach((value) => console.log(value));14. Write a code to iterate over a map
mapis an iterable object and can be iterated using for..of loopmapcan also be iterated by simpleforEachloop
for (let val of map) console.log(val[0], val[1]);for (let key of map.keys()) console.log(key, map.get(key));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
sizeproperty - Map is an iterable object
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 keyNotes
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
filteriterates 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
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
mapiterates 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
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
reduceiterates over the all values of array and passes value, index and array (itself) as the argumentsreduceaccepts an optional initial value which when not provided can be skipped- Function returns a single value after all the iteration
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
function higherOrderFunction() {
function displayHello() {
console.log("Hello");
}
return displayHello;
}
// driver code
var func = higherOrderFunction();
func(); // HelloNotes
Functions can also be stored in variables like other values in JavaScript
References
- https://eloquentjavascript.net/05_higher_order.html
- https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function
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
function callbackExecutor(callback) {
if (typeof callback === "function") {
callback();
}
}
// driver code
function callbackFunc() {
console.log("Callback function executed");
}
callbackExecutor(callbackFunc); // Callback function executedReferences
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
argumentsobject will have a length property as well which gives count of arguments passed
function func() {
for (let key in arguments) {
console.log(arguments[key]);
}
}
// driver code
func(1, "Hello", true);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
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
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
// Regular function as a function statement
function functionName(params) {
//code block
}// Regular function as a function expression
const functionName = function (params) {
//code block
};// 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
functionkeyword functions - Arrow functions with single parameter, round brackets are optional
- Arrow functions with single statement with return, flower brackets and return keywords are optional
const noArgsFunc = () => {
return "No args passed";
};const singleArgFunc = (arg1) => "Argument is " + arg1;const singleArgFunc = (arg1) => {
console.log("Argument is " + arg1);
return arg1;
};const twoArgsFunc = (arg1, arg2) => {
return arg1 + arg2;
};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
varare 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
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
(function IIFE() {
console.log("I am an Immediately invoked function");
})();+(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
(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
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.
function multipleValueReturnFunc() {
const a = 5,
b = 10;
return [a, b];
}
// driver code
const [x, y] = multipleValueReturnFunc();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 valuesfunction* 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
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, 30Notes
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
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, 30Notes
The context inside the function can be accessed using this keyword
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
- https://javascript.info/bind
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
newkeyword - 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
thisinside the function - Constructor function can return an explicit object as well
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
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
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
// currying
function multiply(num1) {
return function (num2) {
return function (num3) {
return num1 * num2 * num3;
};
};
}// partial application
function multiply(num1) {
return function (num2, num3) {
return function (num4) {
return num1 * num2 * num3 * num4;
};
};
}References
- https://towardsdatascience.com/javascript-currying-vs-partial-application-4db5b2442be8
- https://medium.com/better-programming/functional-programming-currying-vs-partial-application-53b8b05c73e3
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
// 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// 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(); // Task2Notes
'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
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,10References
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
newkeyword to constructor function - Object can be created using Class
const object = Object.create({ key: value });const object = {
key: value,
};function getObject(key, value) {
this[key] = value;
}
const object = new getObject("key", "value");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
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key);
}
}for (let key of Object.keys(obj)) {
if (obj.hasOwnProperty(key)) {
console.log(key);
}
}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.valueswhich returns an array of values
console.log(Object.values(obj));for (let value of Object.values(obj)) {
console.log(value);
}Object.values(obj).forEach((value) => console.log(value));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
Dateobject 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
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
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
entriesmethod of Object
const arr = [
["0", "a"],
["1", "b"],
["2", "c"],
];
const obj = Object.fromEntries(arr);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__ setPrototypeOfis used to set the prototype of the object
const obj1 = { a: 1 };
const obj2 = { b: 2 };
obj2.setPrototypeOf(obj1);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
getterandsetteron the properties of object can be used to control the read and write behavior
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
valueaccessor is used to set the value of the propertywritableaccessor is used to set if the property can be modified or notconfigurableaccessor is used to set the property to be configurable or notenumerableaccessor is to set the property to be considered in enumeration
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
preventExtensionsis an Object method which prevents addition of any new property to an objectsealis an Object method which prevents addition and deletion of any property in an objectfreezeis an Object method which prevents addition, deletion and update of any property of an object- There are also methods
isExtensible,isSealedandisFrozenon Object to check
Object.preventExtensions(obj);
Object.isExtensible(obj); // falseObject.seal(obj);
Object.isSealed(obj); // trueObject.freeze(obj);
Object.isFrozen(obj); // trueReferences
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
11. Modify the given object so that it can be used inside a for...of loop
Symbol.iteratorcan be used to define the iterator on the object- The values of the object can accessed with
for..ofthe way we can do it for array
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",
};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
// literal form
let re = /ab+c/g;// 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
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
// 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
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); // falseReferences
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
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, 1017. 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
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 13Notes
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
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: key1Notes
There are lot of other traps used in Proxy apart from get, set, apply
References
- https://javascript.info/proxy
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
19. Show how can we use for..of loop to iterate on a range with given start and end values in an object
// 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
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
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(); // 10File: 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
typeofoperator returns a string indicating the type of the operand
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
// 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"; // 12756References
3. Show the conversion from number to string and vice versa
- Conversion between numbers and strings is a common practical use case
// number to string conversion
const num = 12;
String(num); // "12"
num.toString(); // "12"
num + ""; // "12"// string to number conversion
const str = "12";
Number(str); // 12
+str; // 12
parseInt(str); // 12Notes
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
BigIntis 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
// 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
const num1 = 10,
num2 = 20;
true || false; // true
false || false; // false
false || num1; // 10
0 || num2; // 20
"text" || true; // "text"
num1 > 0 || num2 < 0; // trueconst num1 = 10,
num2 = 20;
true && true; // true
true && false; // false
true && num1; // 10
num1 && num2; // 20
"text" && num1 + num2; // 30
num1 > 0 && num2 < 0; // falseundefined ?? 10; // 10
null ?? 20; // 20
false ?? num1; // false
0 ?? num2; // 0!!10; // true
!!{}; // true
!!""; // false
!!0; // falseNotes
It is not possible to combine both the AND (&&) and OR operators (||) directly with ??
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
- https://developer.cdn.mozilla.net/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT
6. Show the frequently and commonly used methods available on `Number` object with coding examples
isIntegeris used to check if the given number is integer or notparseIntis used to convert a given value in to integerparseFloatis used to convert a given value in to floating numberisNaNis used to check if the given value is NaN or notoFixedis used to limit the number of digits after the decimal placetoPrecisionis used to limit the total number of digits to represent the number
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(56.369).toFixed(2); // 56.37
(59).toFixed(3); // 59.000
(32.458).toPrecision("3"); // 32.5
(98.1).toPrecision(1); // 1e+2Notes
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
NaNis the only value which is not equal to itself and hence comparision operator cannot be used directly to check if a value isNaN
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
absis used to get the absolute value of the given numberflooris used to get the greatest integer smaller than or equal to the given numberceilis used to get the smallest integer greater than or equal to the given numberroundis used to round the given number to the nearest integer.maxis used to get the largest of zero or more numbersminis used to get the smallest of zero or more numberssqrtis used to calculate the square root of the given numberpowis used to calculate the power base on inputstruncis used to return the integer part of a number by removing any fractional digits (method is present on prototype ofNumber)
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)); // -6References
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.epsilonis 2-52, which can be used to verify if this decimal values are matching
0.1 + 0.2 - 0.3 < Number.EPSILON; // trueReferences
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
for (let i = 0; i < str.length; i++) {
console.log(str.charAt(i));
}for (let index in str) {
console.log(str[index]);
}for (let value of str) {
console.log(value);
}[...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
// 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// 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,HTMLReferences
12. Write a code to show the working of `try...catch...finally`
- The
trystatement 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
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
trycan be chained withcatchblock orfinallyblocktry..catchonly works synchronously and for runtime errors
References
13. Show the creation and usage of `symbol` with code
- A "symbol" represents a unique identifier
Symbol.formethod searches for existing symbols in a runtime-wide symbol registry returns the same. If not found, creates a new SymbolSymbol.keyFormethod retrieves the name of the symbol
// new symbol
let symId = Symbol("id");
// global symbol
let symUsername = Symbol.for("username");
// get name by symbol
Symbol.keyFor(symUsername); // usernameNotes
Symbols are skipped by for…in
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
- https://javascript.info/symbol
14. Demonstrate the usage of String Escape Sequences
- Specifies that the following character should be interpreted as a literal character
// 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\\MyApp15. 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.
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.
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray("string")); // false
console.log(Array.isArray(new Array())); // trueReferences
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.
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 automaticallyReferences
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.
var num = 10;
console.log(num); // 10Notes
- 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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
- https://www.geeksforgeeks.org/javascript-var/
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.
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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
- https://www.w3schools.com/js/js_let.asp
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.
const bool = true;
console.log(bool); // TrueNotes
- 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
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
- https://www.w3schools.com/js/js_const.asp
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.
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
- https://www.w3schools.com/js/js_typeof.asp
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
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.
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
- https://medium.com/@jsutcliffe1991/reassignment-redeclaration-of-javascript-variables-var-let-const-3135dc02e769
- https://www.w3schools.com/js/js_let.asp
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.
const a = "js Concepts";
console.log(a); // "js Concepts"
a = "JS Concepts & Challenges"; // This line will cause an errorNotes
- 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
- https://www.w3schools.com/js/js_const.asp
- https://www.geeksforgeeks.org/javascript-const/
- https://dev.to/shearytan/here-is-how-i-change-the-value-of-const-keyword-in-javascript-2gkd
7. Demonstrate Hoisting with var
Show how var is hoisted to the top of its scope.
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.
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.
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.
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.
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:
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.
#### 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:
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:
function fetchData(callback) {
setTimeout(() => {
callback('Data fetched!');
}, 2000);
}
fetchData((data) => {
console.log(data);
});10. What is the difference between `null` and `undefined` in JavaScript?
*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?
*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.
*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.
*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?
*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.
*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?
*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?
*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?
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.
*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.
*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.
javascriptconst 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.
javascriptconst 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.
```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.
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: 326. 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.
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:
- string: Represents text values.
- number: Represents numeric values.
- boolean: Represents true or false.
- null: Represents an intentional absence of any object value.
- undefined: Represents a variable that has been declared but not yet assigned a value.
- symbol: Represents a unique identifier (introduced in ES6).
- bigint: Represents integers with arbitrary precision (introduced in ES11).
Reference Types:
- 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.
// 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.
const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // Output: true
const obj = {};
console.log(Array.isArray(obj)); // Output: false30. 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?
Variable Declarations
ES5: Uses var (function-scoped).
ES6: Introduces let and const (block-scoped).Arrow Functions
ES5: Regular functions with function.
ES6: Arrow functions (() => {}) with lexical this.Template Literals
ES5: String concatenation with +.
ES6: Template literals using backticks for interpolation.Destructuring Assignment
ES5: Manual extraction of values.
ES6: Simplified destructuring for arrays and objects.Modules
ES5: No native support; relies on libraries.
ES6: Native import and export for modules.Promises
ES5: Callbacks for async operations.
ES6: Promises for better async handling.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.
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