JavaScript interview questions and answers for 2025

hero image

JavaScript Interview Questions for Freshers and Intermediate Level

1.

What is JavaScript, and why is it used?

Answer

JavaScript is a high-level, lightweight, interpreted programming language that allows developers to create interactive and dynamic content on web pages. It is one of the three core technologies of the web, alongside HTML and CSS. JavaScript enables features like form validation, content updates without reloading the page (AJAX), animations, and interactive maps.

Key Features of JavaScript:

  • Dynamic Typing: Variables can hold multiple types during runtime.
  • Prototype-Based Inheritance: Objects can inherit properties from other objects.
  • Event-Driven Programming: Reacts to events like clicks, hover, or form submissions.

Example:

 

// Adding interactivity to a button
document.getElementById("clickMe").addEventListener("click", () => {
alert("Button Clicked!");
});
2.

What are the differences between undefined and null?

Answer
  1. undefined: A variable is undefined when it is declared but has not been assigned a value. This state occurs automatically when a variable exists but lacks initialization.
  2. null: A null value is explicitly assigned to a variable to represent “no value” or “empty.”

Comparison Table:

 

Feature undefined null
Meaning Uninitialized variable Explicitly no value
Type "undefined" "object"
Assignable? Automatic (default state) or assigned by developer Assigned by developer

 

Example:

 

let a;
console.log(a); // undefined

let b = null;
console.log(b); // null

let c = 42;
console.log(c); // 42

c = undefined; // acts like deleting variables value
console.log(c); // undefined
3.

What data types can we find in JavaScript?

Answer

JavaScript provides seven primitive types and one non-primitive type:

Primitive Types:

  • String: Represents text. Example: "Hello"
  • Number: Represents integers and floating-point values. Example: 42, 3.14
  • BigInt: Used for very large integers. Example: 123n
  • Boolean: Represents logical values: true or false.
  • Undefined: A declared variable without a value.
  • Null: Represents an intentional absence of value.
  • Symbol: Unique, immutable values often used as object property keys.

Non-Primitive Type:

  • Object: Includes arrays, functions, and other complex entities.

Example:

 

// Primitive Types
let name = "Alice"; // String
let age = 30; // Number
let isAdult = true; // Boolean
let bigNum = 123n; // BigInt

// Non-Primitive Type
let person = { name: "Alice", age: 30 };
4.

What is the difference between let, var, and const?

Answer
Feature var let const
Scope Function-scoped Block-scoped Block-scoped
Hoisting Hoisted; initialized to undefined Hoisted; not initialized Hoisted; not initialized; requires value assignment
Redeclaration Allowed Not allowed Not allowed
Reassignment Allowed Allowed Not allowed

 

Example:

 

console.log(c); // `c` is hoisted up to here; its initial value is `undefined`

let a = 10;
y = 20; // Reassignment allowed

const b = 20;
// z = 20; // Error: Reassignment not allowed

var c = 30;
c = 33; // Reassignment allowed
var c = 333; // Redeclaration allowed
5.

What are template literals in JavaScript?

Answer

Template literals, introduced in ES6, provide a more convenient way to create strings by embedding expressions and multi-line strings.

Key Features:

  1. Enclosed in backticks (“).
  2. Allow embedding expressions using ${expression}.
  3. Support multi-line strings without special characters like \\n.

Example:

 

const name = "Alice";
const age = 25;

// Single-line template literal
const message = `My name is ${name} and I am ${age} years old.`;

// Multi-line string
const paragraph = `This is a
multi-line string without
using any escape characters.`;

console.log(message); // My name is Alice and I am 25 years old.
console.log(paragraph); // Prints multi-line text
6.

What are JavaScript closures?

Answer

A closure is a function that “remembers” its lexical scope even when executed outside that scope. Closures are often used to create private variables and encapsulate functionality. But also, any callback function (a function passed as an argument to another function) is also automatically a closure.

How it works:

  • Inner functions have access to variables of their outer scope.
  • The outer function’s variables remain accessible even after the function has executed.

Example:

 

function createCounter() {
let count = 0;
return function () {
count++;
return count;
};
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

 

Explanation:

  • The counter function has access to count, even though createCounter has finished execution.
7.

Explain the concept of hoisting.

Answer

Hoisting is a JavaScript mechanism where declarations (variables and functions) are moved to the top of their scope before code execution. For variables, however, only the declaration is hoisted, not the initialization.

Key Points:

  1. Variables declared with var are initialized to undefined.
  2. let and const declarations are hoisted but not initialized (they remain in the “temporal dead zone (TDZ)”).
  3. Function declarations are fully hoisted.

Example:

 

console.log(a); // undefined (hoisted)
var a = 10;

// console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;

foo(); // Works because function is hoisted
function foo() {
console.log("Hello");
}
8.

What are JavaScript events?

Answer

Events are actions or occurrences that happen in the browser, which JavaScript can detect and respond to. Examples include user interactions like clicking a button, hovering over an element, or pressing a key.

How Events Work:

  • Events are triggered by user actions or the browser itself (e.g., loading a page).
  • JavaScript provides event listeners to “listen” for and handle these events.

Common Events:

  • click: Triggered when an element is clicked.
  • mouseover: Triggered when the cursor hovers over an element.
  • keydown: Triggered when a key is pressed.

Example:

 

// Adding a click event listener to a button
document.getElementById("myButton").addEventListener("click", () => {
alert("Button was clicked!");
});

 

In this example:

  • addEventListener attaches an event to the element with the ID myButton.
  • The callback function runs when the event occurs.
9.

What is an IIFE (Immediately Invoked Function Expression)?

Answer

An IIFE is a function that is executed immediately after it is defined. It’s commonly used to create a private scope and avoid polluting the global namespace.

Syntax:

 

(() => {
console.log("IIFE runs immediately!");
})();

 

Why Use IIFEs?

  • To create a private scope.
  • To avoid variable conflicts in the global namespace.
  • Useful in modular programming.
  • For quick garbage collection of the function’s scope (if the IIFE neither creates a closure nor returns a value, its entire scope is garbage collected as soon as execution finishes, because nothing references its contents anymore)

Example:

 

 

// Using an IIFE to create a private scope
(function () {
const privateVar = "I'm private!";
console.log(privateVar);
})();

// privateVar is not accessible here
// console.log(privateVar); // Error: privateVar is not defined
10.

What is the difference between == and ===?

Answer
Operator Description Example
== Checks for value equality (with type coercion) 5 == "5"true
=== Checks for strict equality (no coercion) 5 === "5"false

 

Type Coercion with ==:

  • When using ==, JavaScript converts the operands to the same type before comparing.

Strict Equality with ===:

  • === does not perform type conversion; both value and type must match.

Example:

console.log(5 == "5"); // true (type coercion)
console.log(5 === "5"); // false (different types)

console.log(null == undefined); // true (special case)
console.log(null === undefined); // false (strict check)

 

11.

What is the typeof operator?

Answer

The typeof operator is used to determine the type of a value or variable in JavaScript. It returns a string indicating the type.

Syntax:

typeof operand;

Return Values:

  • "string": For strings.
  • "number": For numbers.
  • "boolean": For booleans.
  • "undefined": For uninitialized variables.
  • "object": For objects, arrays, and null.
  • "function": For functions.

Examples:

 

console.log(typeof "Hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof {}); // "object"
console.log(typeof null); // "object" (a known quirk of JavaScript)
console.log(typeof function(){}); // "function"
12.

What are JavaScript promises?

Answer

A promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation. It simplifies handling asynchronous tasks by avoiding callback hell.

States of a Promise:

  1. Pending: Initial state, neither fulfilled nor rejected.
  2. Fulfilled: Operation completed successfully.
  3. Rejected: Operation failed.

Methods:

  • .then(): Handles success.
  • .catch(): Handles errors.
  • .finally(): Executes code after the promise settles (regardless if fulfilled or rejected).

Example:

 

const fetchData = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data loaded successfully!");
}, 1000);
});

fetchData
.then((data) => console.log(data)) // "Data loaded successfully!"
.catch((error) => console.log(error))
.finally(() => console.log("Operation complete."));

 

 

13.

What is an arrow function? How is it different from a normal function?

Answer

Arrow functions, introduced in ES6, are a concise/brief way to write functions. They also have a lexical binding of this, meaning they inherit this from their surrounding context instead of having their own.

Syntax:

 

const functionName = (parameters) => { body };

 

Differences from Regular Functions:

  1. this Binding: Arrow functions don’t have their own this.
  2. Conciseness: Single-line arrow functions can omit {} and return.

Example:

 

// Regular function
function add(a, b) {
return a + b;
}

// Arrow function
const addArrow = (a, b) => a + b;

console.log(add(2, 3)); // 5
console.log(addArrow(2, 3)); // 5

 

Key Use Case: Arrow functions are ideal for callbacks, especially in array methods or event handlers.

14.

What is event delegation in JavaScript?

Answer

Event delegation is a technique where you attach a single event listener to a parent element to manage events for multiple child elements. It is particularly useful for dynamic content or performance optimization.

How It Works:

  • Instead of attaching multiple listeners to individual elements, add one listener to a common parent.
  • Use event.target to identify the element which triggered the event.

Example:

// HTML:
// <div id="parent">
// <button>Click me</button>
// <span>You can also click me</span>
// </div>

document.getElementById("parent").addEventListener("click", (e) => {
if (e.target.tagName === "BUTTON") {
console.log("Button clicked!");
}

if (e.target.tagName === "SPAN") {
console.log("Span clicked!");
}
});

 

Benefits:

  1. Fewer event listeners improve performance.
  2. Seamlessly handles dynamically added elements.
15.

What is the this keyword in JavaScript?

Answer

The this keyword refers to the context in which a function is executed. Its value depends on how and where the function is called.

Key Rules for this:

  1. Global Context (Non-Strict Mode): Refers to the global object (window in browsers).
  2. Global Context (Strict Mode): this is undefined.
  3. Object Method: Refers to the object calling the method.
  4. Arrow Function: Inherits this from the surrounding lexical context.

Example:

 

// Global Context
console.log(this); // window (in browsers)

// Inside an object
const obj = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}`);
},
};
obj.greet(); // Hello, Alice

// Arrow function
const arrow = () => console.log(this);
arrow(); // Inherits from global or enclosing context
16.

What are prototypes in JavaScript?

Answer

In JavaScript, every object has a hidden property called __proto__ or prototype, which is a reference to another object. Prototypes are the foundation of inheritance in JavaScript, allowing objects to share properties and methods.

Key Concepts:

  1. Prototype Chain: When accessing a property or method, JavaScript first checks the object itself. If not found, it traverses up the prototype chain.
  2. Object.prototype is the topmost object in the prototype chain.

Example:

 

function Person(name) {
this.name = name;
}

Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name}`);
};

const alice = new Person("Alice");
alice.greet(); // Hello, my name is Alice
console.log(alice.toString()); // [object Object]
console.log(alice.__proto__ === Person.prototype); // true

 

Explanation:

  • The greet method is defined on Person.prototype.
  • When alice.greet() is called, JavaScript checks alice and finds it in the prototype.
  • When alice.toString() is called, JavaScript does not find this in the Person prototype, so a default method of Object.prototype is used.
17.

Explain the difference between synchronous and asynchronous code.

Answer
  1. Synchronous Code:
    • Executes line by line in the order it is written.
    • Blocks further execution until the current task completes.

    Example:

 

console.log("Start");
console.log("Middle");
console.log("End");
// Output: Start, Middle, End

 

  1. Asynchronous Code:
    • Executes independently of the main thread.
    • Uses mechanisms like timeouts, callbacks, events, promises, or async/await to handle tasks.

    Example:

 

console.log("Start");
setTimeout(() => console.log("Async Task"), 1000);
console.log("End");
// Output: Start, End, Async Task

 

Key Tools for Asynchronous JavaScript:

  • Timeouts
  • Callbacks
  • Promises
  • async/await
18.

What is the Event Loop in JavaScript?

Answer

The Event Loop is a mechanism that allows JavaScript to handle asynchronous operations and execute callbacks after the current execution stack is cleared.

Steps in the Event Loop:

  1. The main thread runs synchronous code.
  2. Asynchronous operations (e.g., setTimeout) are sent to the Web APIs.
  3. Once asynchronous tasks complete, their callbacks are pushed to the task queue.
  4. The Event Loop checks the call stack. If it’s empty, it processes tasks from the task queue.

Example:

 

console.log("Start");

setTimeout(() => console.log("Timeout"), 0);

console.log("End");
// Output: Start, End, Timeout

 

Explanation:

  • setTimeout is asynchronous, so its callback is added to the task queue.
  • The Event Loop processes the task queue after synchronous code completes.
19.

What is the difference between map() and forEach() array methods?

Answer

Both methods are used to iterate over arrays, but they differ in their behavior:

 

Feature map() forEach()
Return Value Returns a new array Does not return anything
Chaining Can be chained Cannot be chained
Purpose Transforms array elements Executes a function for each item

 

Example:

 

const numbers = [1, 2, 3];

// map()
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6]

// forEach()
numbers.forEach((num) => console.log(num * 2));
// Outputs: 2, 4, 6 (but no new array is returned)
20.

How do you debug JavaScript code?

Answer

Common Debugging Techniques:

  1. console.log() (or even better console.debug()): The most basic way to display values of various expressions and check execution flow.
  2. Browser Developer Tools:
    • Breakpoints: Pause execution at specific lines.
    • Watch Expressions: Monitor variables during execution.
  3. Error Handling:
    • Use try...catch to handle errors gracefully.
  4. Debugging Keywords:
    • Use debugger to pause execution at a specific point.

 

function test() {
debugger;
console.log("Debugging");
}

test();
21.

What is the difference between splice() and slice() array methods?

Answer
Method splice() slice()
Modifies Original Array? Yes No
Purpose Adds/removes elements Extracts a portion of the array
Return Value Removed elements A new array containing extracted items

 

Example:

 

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

// splice()
const removed = arr.splice(1, 2, "a", "b");
console.log(arr); // [1, "a", "b", 4, 5] - modified array
console.log(removed); // [2, 3] - removed elements

// slice()
const sliced = arr.slice(1, 3);
console.log(sliced); // ["a", "b"] - extracted elements
console.log(arr); // [1, "a", "b", 4, 5] - unchanged array
22.

Explain usage of default parameters in JavaScript?

Answer

Default parameters allow functions to initialize parameters with default values if no value or undefined is passed.

Syntax:

 

function functionName(param = defaultValue) {
// Function body
}

 

Example:

 

function greet(name = "Guest") {
console.log(`Hello, ${name}!`);
}

greet(); // Hello, Guest!
greet("Alice"); // Hello, Alice!
23.

What are JavaScript modules?

Answer

JavaScript modules allow code to be split into separate files and reused across different parts of an application. They promote encapsulation and improve code maintainability.

Exporting and Importing:

  1. Exporting:
    • Named Exports:

 

export const name = "Alice";
export function greet() {
console.log("Hello");
}

 

  • Default Export:

 

export default function () {
console.log("Default Export");
}

 

2. Importing:

 

import { name, greet } from './module.js';
import defaultFunc from './module.js';
24.

What is the difference between .call(), .apply(), and .bind()?

Answer
Method call() apply() bind()
Invocation Invokes the function immediately Invokes the function immediately Returns a new bound function
Arguments Arguments passed individually Arguments passed as an array Arguments passed individually

 

Example:

 

const person = {
name: "Alice",
greet(age) {
console.log(`${this.name} is ${age} years old.`);
},
};

const anotherPerson = { name: "Bob" };

// call()
person.greet.call(anotherPerson, 25); // Bob is 25 years old

// apply()
person.greet.apply(anotherPerson, [30]); // Bob is 30 years old

// bind()
const boundFunc = person.greet.bind(anotherPerson, 35);
boundFunc(); // Bob is 35 years old
25.

What are destructuring assignments in JavaScript?

Answer

Destructuring allows unpacking elements from arrays or properties from objects into distinct variables.

Array Destructuring:

 

const arr = [1, 2, 3];
const [a, , c] = arr;

console.log(a, c); // 1, 3

 

Object Destructuring:

 

const obj = { name: "Alice", age: 25 };
const { name } = obj;

console.log(name); // Alice
26.

Explain the difference between mutable and immutable objects.

Answer
  • Mutable Objects: Can be changed after creation. Example: Arrays and Objects.
  • Immutable Objects: Cannot be changed once created. Example: Strings and numbers.

Example:

 

let arr = [1, 2, 3];
arr.push(4); // Changes the array (mutable)
console.log(arr); // [1, 2, 3, 4]

let str = "hello";
str[0] = "H"; // Does not change the string (immutable)
console.log(str); // "hello"
27.

What are higher-order functions in JavaScript?

Answer

Higher-order functions are functions that can:

  1. Take other functions as arguments.
  2. Return other functions.

Example:

 

function higherOrderFunction(callback) {
return callback();
}

higherOrderFunction(() => console.log("Hello from callback!"));
28.

What is the spread operator ()?

Answer

The spread operator expands elements of an array or object into individual elements.

Examples:

 

const arr = [1, 2, 3];
console.log([...arr, 4, 5]); // [1, 2, 3, 4, 5]

const obj = { name: "Alice" };
console.log({ ...obj, age: 25 }); // { name: "Alice", age: 25 }
29.

What is the rest operator ()?

Answer

The rest operator groups elements of an array or function arguments into a new variable.

Examples:

 

const arr = [1, 2, 3, 4];
const [ first, ...remainingElements ] = arr;
console.log(first); // 1
console.log(remainingElements); // [ 2, 3, 4, 5 ]


function testFunction(name, role, ...remainingArguments) {
console.log(remainingArguments);
}
testFunction("foo", "bar", "baz", 42); // [ "baz", 42 ]
testFunction("Alice", "Admin", true, null, 123) // [ true, null, 123 ]
testFunction("Bob", "User") // []
30.

Explain the difference between shallow and deep copying in JavaScript.

Answer
  • Shallow Copy: Only copies the first level of an object. Changes to nested objects affect the original too.
  • Deep Copy: Recursively copies all levels of an object.

Example:

 

const original = { a: 1, b: { c: 2 } };
const shallow = { ...original };
shallow.b.c = 3;

console.log(original.b.c); // 3 (affected by shallow copy)

// Deep Copy (using JSON methods)
const deep = JSON.parse(JSON.stringify(original));
deep.b.c = 4;

console.log(original.b.c); // 3 (unchanged)

JavaScript Interview Questions for Experienced Levels

1.

What are JavaScript Promises, and how do they differ from callbacks?

Answer

Promises simplify asynchronous programming by providing a cleaner syntax and better error handling compared to callbacks. They represent a value that may be available now, or in the future, or never.

States of a Promise:

  1. Pending: Initial state, neither fulfilled nor rejected.
  2. Fulfilled: Operation completed successfully.
  3. Rejected: Operation failed.

Difference from Callbacks:

  • Promises: Chainable with .then() and .catch() methods, which makes them easier to read and maintain.
  • Callbacks: Often result in callback hell, making the code less readable.

Example:

Callback based approach:

 

function step1(data, callback) {
// do something async or time-consuming
if (/* everything ok */) {
callback(null, `${data} -> Step 1`);
} else {
callback("Error in Step 1");
}
}

function step2(data, callback) {
// do something async or time-consuming
if (/* everything ok */) {
callback(null, `${data} -> Step 2`);
} else {
callback("Error in Step 2");
}
}

function step3(data, callback) {
// do something async or time-consuming
if (/* everything ok */) {
callback(null, `${data} -> Step 3`);
} else {
callback("Error in Step 3");
}
}

// Callback hell example
step1("Start", (err, result1) => { // proceed with `step1`
if (err) return console.error(err); // handling error of `step1`

step2(result1, (err, result2) => { // proceed with `step2`
if (err) return console.error(err); // handling error of `step2`

step3(result2, (err, result3) => { // proceed with `step3`
if (err) return console.error(err); // handling error of `step3`

console.log(`${result3} -> FINISH`); // finish
});
});
});

 

Promise-based approach:

 

function step1(data) {
return new Promise((resolve, reject) => {
// do something async or time-consuming
(/* everything ok? */) ? resolve(`${data} -> Step 1`) : reject("Error in Step 1");
});
}

function step2(data) {
return new Promise((resolve, reject) => {
// do something async or time-consuming
(/* everything ok? */) { ? resolve(`${data} -> Step 2`) : reject("Error in Step 2");
});
}

function step3(data) {
return new Promise((resolve, reject) => {
// do something async or time-consuming
(/* everything ok? */) ? resolve(`${data} -> Step 3`) : reject("Error in Step 3");

});
}

// Chained Promises
step1("Start") // proceed with `step1`
.then(step2) // proceed with `step2`
.then(step3) // proceed with `step3`
.then(finalResult => console.log(`${finalResult} -> FINISH`)) // finish
.catch(err => console.error(err)); // handling error in any of steps
2.

What is async/await, and how does it improve asynchronous code?

Answer

async/await provides a cleaner, more declarative, way to work with Promises. Functions declared with async return a Promise, and await pauses execution of the code following it until the Promise resolves/rejects.

Example:

 

// based on the promise-based example from above
async function processSteps() {
try {
const result1 = await step1("Start"); // proceed with `step1`
const result2 = await step2(result1); // proceed with `step2`
const finalResult = await step3(result2); // proceed with `step3`
console.log(finalResult); // finish
} catch (error) {
console.error(error); // handling error in any of steps
}
}

processSteps();

 

3.

Explain the concept of a JavaScript event loop.

Answer

The event loop is a mechanism that allows JavaScript to handle asynchronous tasks by managing the call stack and task queue.

Key Concepts:

  • Call Stack: Executes synchronous code.
  • Task Queue: Holds callbacks from asynchronous operations (e.g., setTimeout).
  • Microtask Queue: Higher priority queue for promises and MutationObserver.

Example:

 

console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
Promise.resolve().then(() => console.log("Promise"));
console.log("End");

// Output: Start, End, Promise, Timeout
4.

What are JavaScript Generators?

Answer

Generators are functions that can pause and resume their execution using yield. They are declared with function*. The generators can also be iterable.

Example:

 

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

// Using the generator manually
const gen = generator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3

// Using the generator as an iterable
for (const value of generator()) {
console.log(value);
}

 

 

5.

Explain the difference between var, let, and const.

Answer
Feature var let const
Scope Function-scoped Block-scoped Block-scoped
Hoisting Hoisted; initialized to undefined Hoisted; not initialized Hoisted; not initialized; requires value assignment
Redeclaration Allowed Not allowed Not allowed
Reassignment Allowed Allowed Not allowed

 

Example:

 

{ // we're opening a new block of code (new block scope!)


// var
console.log(x); // `x` is hoisted up to here; its initial value is `undefined`
var x = 10;
x = 20; // Reassignment allowed
var x = 30; // Redeclaration allowed


// let
// console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 10;
y = 20; // Reassignment allowed
// let y = 30; // Error: Redeclaration not allowed


// const
// console.log(z); ReferenceError: Cannot access 'z' before initialization
const z = 10;
// z = 20; // Error: Reassignment not allowed


} // we're closing the block of code


console.log(x); // `x` is available also in this higher scope
console.log(y); // `y` is not available in this scope!
console.log(z); // `z` is not available in this scope!
6.

What are setTimeout and setInterval, and how do they differ?

Answer
  • setTimeout: Executes a function after a specified delay.
  • setInterval: Executes a function repeatedly at specified intervals.

Example:

 

// setTimeout
setTimeout(() => console.log("Hello after 1 second"), 1000);

// setInterval
setInterval(() => console.log("Repeating every second"), 1000);
7.

What are WeakMap and WeakSet, and how do they compare to Map and Set?

Answer

WeakMap and WeakSet store weak references to objects, enabling automatic garbage collection when there are no other strong references to the objects. They are specialized collections designed for scenarios where objects should not prevent their own garbage collection.

Comparison:

Feature Map WeakMap Set WeakSet
Keys Any type Only objects Not applicable Not applicable
Values Any type Any type Any type Only objects
Garbage Collection No Yes No Yes
Iteration Iterable Not iterable Iterable Not iterable
Use Cases General-purpose key-value pairs Ephemeral key-value pairs General-purpose unique values Ephemeral unique objects

 

Explanation:

Map:

  • A collection of key-value pairs.
  • Keys and values can be of any type.
  • Iterable via methods like map.keys(), map.values(), and map.entries().
  • Objects as keys prevent garbage collection while in the Map.

WeakMap:

  • A collection of key-value pairs where keys must be objects.
  • Keys are weakly referenced, allowing their garbage collection if no other references exist.
  • Not iterable, designed for specific use cases like private data for objects.
const wm = new WeakMap();
let obj = { name: "Alice" };

wm.set(obj, "Private Data");

console.log(wm.get(obj)); // "Private Data"

obj = null;
// The object is now eligible for garbage collection, and the entry is removed.

 

Set:

  • A collection of unique values.
  • Can store any type of value (primitive or object).
  • Iterable via set.keys() or for...of.

WeakSet:

  • A collection of unique object references.
  • Objects are weakly referenced and eligible for garbage collection when no longer referenced elsewhere.
  • Not iterable.

Example:

 

const ws = new WeakSet();
let obj = { id: 1 };

ws.add(obj);

console.log(ws.has(obj)); // true

obj = null;
// The object is now eligible for garbage collection, and the entry is removed.

 

Key Differences:

  • Garbage Collection: Only WeakMap and WeakSet enable garbage collection of their contents.
  • Iterability: Map and Set are iterable, while WeakMap and WeakSet are not.
  • Key and Value Types: WeakMap and WeakSet strictly require objects as keys or values, while Map and Set allow any type.
8.

What is the new keyword in JavaScript?

Answer

The new keyword creates an instance of an object with the specified constructor function.

Example:

 

function Person(name) {
    this.name = name;
}


class Animal {
  constructor(name) {
  this.name = name
  }
}


const person = new Person("Alice");
console.log(person.name); // Alice


const cat = new Animal("Fluffy");
console.log(cat.name); // Fluffy
9.

How does JavaScript handle memory management and present examples of common memory management issues?

Answer

JavaScript uses automatic memory management, primarily through a process called garbage collection. The engine allocates memory when variables, objects, or functions are created and automatically reclaims it when they are no longer needed.

Key Concepts of JavaScript Memory Management

1. Memory Allocation:

  • Memory is allocated for variables, objects, and functions when they are created.
  • Example:

 

let number = 42; // Memory allocated for a number
const obj = { key: "value" }; // Memory allocated for an object

 

2. Garbage Collection:

The garbage collector identifies and frees memory that is no longer reachable. JavaScript primarily uses the Mark-and-Sweep Algorithm for garbage collection.

  • Mark Phase: Starts from the “roots” (e.g., global variables and the call stack) and marks all reachable objects.
  • Sweep Phase: Removes all unmarked objects and reclaims their memory.

3. Roots and Reachability:

  • Roots: References accessible globally, such as global variables and objects in the call stack.
  • Reachable Objects: Objects that can be accessed directly or indirectly from the roots.

Common Memory Management Issues

1. Memory Leaks:

Memory that is no longer needed but cannot be reclaimed by the garbage collector. Causes include:

  • Unintentionally retained references:

 

let obj = {};
const map = new Map();

map.set(obj, "value");

obj = null;
// The `obj` is still referenced by the Map and won't be garbage collected.

 

  • Global Variables: Variables declared without let, const, or var become global and persist until the application exits.

 

function leak() {
globalVar = "I am a leak"; // This creates a global variable.
}

 

2. Closures Retaining References:

Closures can unintentionally retain references, preventing garbage collection.

 

function outer() {
let largeData = new Array(1000).fill("data");

return function() {
console.log("Closure");
};
}

const closure = outer();
// `largeData` is not garbage collected because `closure` retains a reference to `outer`.
10.

What is the difference between deep copy and shallow copy?

Answer
  • Shallow Copy: Copies only the first level of the object.
  • Deep Copy: Recursively copies all levels.

Example:

 

const obj = { a: 1, b: { c: 2 } };
const shallow = { ...obj };

shallow.b.c = 3; // Affects original object
console.log(obj.b.c) // outputs 3!

const deep = structuredClone(obj);
deep.b.c = 4; // Does not affect original object

// the same happens for objects in arrays
const arr = [ { name: "Alice", age: 18 } ];
const copiedArr = [ ...arr ];

copiedArr[0].age = 42;
console.log(arr[0]) // { name: "Alice", age: 42 }

 

 

11.

Explain Currying in JavaScript.

Answer

Currying transforms a function with multiple arguments into a sequence of functions that can be called incrementally, accepting one or more arguments at a time, until all arguments are provided.

Key Features of Currying:

  • Allows functions to be invoked partially, one argument at a time, or in groups of arguments.
  • The curried function keeps returning a new function until all the required arguments are provided.
  • Once all arguments are supplied, the original function is executed

Example:

 

function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
// Call the original function if enough arguments are provided
return fn(...args);
}

// Otherwise, return a new function
return (...nextArgs) => curried(...args, ...nextArgs);
};
}

const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);

console.log(curriedAdd(1)(2)(3)); // 6 (one argument at a time)
console.log(curriedAdd(1, 2)(3)); // 6 (two arguments at a time)
console.log(curriedAdd(1, 2, 3)); // 6 (all arguments at once)

 

12.

What are JavaScript decorators?

Answer

Decorators are annotations or modifiers that allow you to modify the behavior of classes, class methods, or properties. They act as higher-order functions, taking a target object and modifying its behavior or metadata. Decorators can be used to add additional logic to properties, methods, or even entire classes.

Note: Decorators are a stage-2 proposal in ECMAScript, meaning they are still experimental and may change in the future. Currently, they can be used with Babel or similar tools that support experimental JavaScript features.

How Decorators Work?

Decorators are applied to classes or methods as annotations. They typically modify the class behavior or its method descriptors. Decorators are not natively available in JavaScript yet, but they are widely used eg. in TypeScript.

Decorators in JavaScript are functions that receive the following parameters:

  • For class decorators, it receives the constructor of the class.
  • For method decorators, it receives the target object, the method name, and the method descriptor.
  • For property decorators, it receives the target object and the property key.

Example:

 

// Property decorator - makes a property readonly
function readonly(target, key, descriptor) {
  // Define the getter and setter for the property
  let value = descriptor.initializer ? descriptor.initializer() : undefined;


  descriptor.get = function() {
    return value;
  };


  descriptor.set = function(newValue) {
    console.error(`Cannot assign to read-only property '${key}'`);
  };


  return descriptor;
}


// Method decorator that accepts an optional custom argument;
// the methos logs method calls and their arguments
function log(message = "LOG") {
  return function(target, key, descriptor) {
    const originalMethod = descriptor.value;


    descriptor.value = function(...args) {
      console.log(`[${message}]: Method \`${key}\` called with arguments: ${args}`);
      return originalMethod.apply(this, args);
    };


    return descriptor;
  };
}


// Class decorator - adds a new method to the class dynamically
function withHello(target) {
  target.prototype.hello = function() {
    console.log("Hello from the decorated class!");
  };
}


// Applying the decorators
@withHello
class MyClass {
constructor() {
    // Some constructor logic if necessary
  }
    
  @readonly
  name = "AliceBot"; // The name property is now read-only


  @log('ATTENTION!')
  add(a, b) {
    return a + b;
  }
  
  @log
  multiply(a, b) {
  return a * b;
  }
}


// Testing the decorators
const instance = new MyClass();


instance.hello(); // Logs: Hello from the decorated class!


console.log(instance.name); // AliceBot
p.name = "Bob The Bot"; // Error: Cannot assign to read only property 'name' of object


console.log(instance.add(2, 3)); // Logs: [ATTENTION!]: Method `add` called with arguments: 2,3
console.log(instance.multiply(4, 5)); // Logs: [LOG]: Methos `multiply` called with arguments: 4,5

 

Use Cases of decorators:

  1. Method Modification: You can add logging, caching, validation, or transformation logic to methods.
  2. Class Behavior Change: You can modify the constructor or extend the functionality of a class without directly modifying its code.
  3. Aspect-Oriented Programming: Useful in separating cross-cutting concerns, like logging, security, or transaction handling.
  4. Framework Integration: Used in frameworks like Angular or NestJS to define routes, inject dependencies, and apply other configuration settings.
13.

What is memoization in JavaScript?

Answer

Memoization is an optimization technique to store the results of expensive function calls and return the cached result for the same inputs.

Example:

 

function memoize(fn) {
  const cache = {};
  
  return function (...args) {
    const key = JSON.stringify(args);
    
    let result = cache[key];
    
    if (!result) {
    result = fn(...args);
    cache[key] = result;
    }
    
    return result;
  };
}


const factorial = memoize((n) => (n === 0 ? 1 : n * factorial(n - 1)));


console.time('first');
console.log(factorial(12)); // 479001600
console.timeEnd('first') // 0.262939453125 ms


console.time('second');
console.log(factorial(12)); // 479001600 - the result is obviously the same ;)
console.timeEnd('second') // 0.105224609375 ms - but the second call was faster

 

14.

What are proxies in JavaScript?

Answer

Proxies allow intercepting and customizing operations on objects like reading, writing, or deleting properties.

Example:

 

const handler = {
get: (target, property) => {
return property in target ? target[property] : "Property not found";
},
};

const obj = { name: "Alice" };
const proxy = new Proxy(obj, handler);

console.log(proxy.name); // Alice
console.log(proxy.age); // Property not found

 

 

15.

What is the difference between .call(), .apply(), and .bind()?

Answer
Method call() apply() bind()
Invocation Invokes the function immediately Invokes the function immediately Returns a new bound function
Arguments Arguments passed individually Arguments passed as an array Arguments passed individually

 

Example:

 

const person = {
name: "Alice",
greet(age) {
console.log(`${this.name} is ${age} years old.`);
},
};

const anotherPerson = { name: "Bob" };

// call()
person.greet.call(anotherPerson, 25); // Bob is 25 years old

// apply()
person.greet.apply(anotherPerson, [30]); // Bob is 30 years old

// bind()
const boundFunc = person.greet.bind(anotherPerson, 35);
boundFunc(); // Bob is 35 years old
16.

What is the difference between Object.freeze() and Object.seal()?

Answer
Feature Object.freeze() Object.seal()
Adding Properties Not Allowed Not Allowed
Modifying Properties Not Allowed Allowed
Deleting Properties Not Allowed Not Allowed

 

Example:

 

const obj = { name: "Alice" };

Object.freeze(obj);
obj.name = "Bob"; // No effect
delete obj.name; // No effect
obj.age = 25; // No effect
console.log(obj); // { name: "Alice" }

// ---

const obj2 = { age: 25 };

Object.seal(obj2);
obj2.age = 30; // Allowed
delete obj2.age; // No effect
obj2.name = "Bob" // No effect
console.log(obj2); // { age: 30 }
17.

Explain this in different contexts.

Answer

The value of this depends on the execution context:

  1. Global Scope: Refers to the global object (window in browsers, global in Node.js).

 

console.log(this); // Window (in browsers)

 

     2. Object Method: Refers to the object invoking the method.

 

const obj = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}`);
}
};
obj.greet(); // Hello, Alice

 

     3. Arrow Functions: Inherits this from the enclosing lexical context.

 

const arrowFunc = () => console.log(this);
arrowFunc(); // Window (global)

 

    4. Constructor Function: Refers to the instance created by the constructor.

 

function Person(name) { this.name = name; }
const alice = new Person("Alice");
console.log(alice.name); // Alice

 

18.

What is the purpose of Object.create()?

Answer

Object.create() creates a new object that inherits from a specified prototype object. It allows you to set the prototype chain and also define additional properties or methods on the newly created object. This method is particularly useful for establishing inheritance hierarchies without the need for constructor functions or classes.

Key Points:

  1. Prototype Chain Setup: It allows for direct setting of the prototype of the new object.
  2. Property Definitions: You can also pass an optional second argument, which defines new properties on the newly created object, much like Object.defineProperties().
  3. Shallow Inheritance: It provides a straightforward way to set up inheritance without needing to explicitly call constructors or deal with prototypes in the constructor function style.

Example:

 

const parent = {
greet() {
console.log("Hello");
}
};
const child = Object.create(parent);


child.greet(); // Hello
console.log(Object.getPrototypeOf(child) === parent); // true

 

19.

What are mixins in JavaScript?

Answer

Mixins are a way to extend the functionality of objects or classes by combining multiple sources.

Example:

 

const canFly = {
fly() {
console.log("I can fly!");
},
};

const canSwim = {
swim() {
console.log("I can swim!");
},
};

class Animal {}
Object.assign(Animal.prototype, canFly, canSwim);

const duck = new Animal();
duck.fly(); // I can fly!
duck.swim(); // I can swim!
20.

What is the instanceof operator?

Answer

The instanceof operator checks if an object is an instance of a specific constructor or has the constructor in its prototype chain.

Example:

 

function Person() {}
const alice = new Person();

console.log(alice instanceof Person); // true
console.log(alice instanceof Object); // true
21.

What are tagged template literals?

Answer

Tagged templates allow you to customize string interpolation by using a function to process the template literal. When a template literal is prefixed with a function, the function is called with the template literal’s parts (strings) and the interpolated values as arguments. This allows you to customize the behavior of string interpolation.

Example:

 

function tag(strings, ...values) {
return strings.reduce((result, str, i) => {
// If there's no value, substitute with a default
let value = i < values.length ? values[i] ?? "N/A" : "";

// Detect if the value is a number and format it (both salary and age)
if (typeof value === 'number' && value > 100) {
// Add currency formatting for all numbers above 100
value = `$${value.toFixed(2)}`;
}

// Concatenate the string parts and the formatted value
return result + str + value;
}, "");
}

const name = "Alice";
const age = 25;
const salary = 50000;
const city = undefined; // Missing value

console.log(tag`My name is ${name}, I am ${age} years old, earn ${salary} annually, and live in ${city}.`);
// My name is Alice, I am 25 years old, earn $50000.00 annually, and live in N/A.
22.

Explain Symbol in JavaScript.

Answer

Symbol is a primitive data type in JavaScript that is unique and immutable. It’s primarily used to create unique property keys, often for object properties, ensuring that there are no naming conflicts. Symbols can be used to define keys that are not easily accessible or overwritten, making them ideal for use in cases where privacy or unique identifiers are required.

Key Features of Symbol:

  1. Uniqueness: every Symbol is guaranteed to be unique, even if two symbols are created with the same description.
  2. Immutability: once a symbol is created, its value cannot be changed.
  3. Non-enumerability: symbols are not enumerable in object iteration methods such as for...in, Object.keys(), or JSON.stringify(), making them useful for creating private or internal properties.
  4. Used for Unique Property Keys: symbols are often used to define object properties that are meant to be unique, preventing naming collisions.

Example: Using Symbol for Unique Property Keys:

 

// Creating symbols with a description (used for debugging purposes)
const sym1 = Symbol("description");
const sym2 = Symbol("description");

const obj = {
[sym1]: "value",
[sym2]: "another value"
};

console.log(obj[sym1]); // "value"
console.log(obj[sym2]); // "another value"

// Check if two symbols with the same description are equal
console.log(sym1 === sym2); // false, even though descriptions were the same

// Object.keys does not include symbols
console.log(Object.keys(obj)); // []

// Symbols are not serialized by JSON.stringify
console.log(JSON.stringify(obj)); // {}
23.

What is the purpose of Reflect in JavaScript?

Answer

The Reflect object is a built-in JavaScript object that provides methods for performing low-level operations on objects.

It is similar to the Proxy API in that it allows you to interact with object properties and operations, but it is not directly involved in intercepting operations like a Proxy. Instead, Reflect provides methods that enable easier and more standardized interaction with objects.

Reflect methods are generally used to:

  1. Perform operations such as getting, setting, or deleting object properties in a more predictable and functional way.
  2. Make the object manipulation code more concise and consistent by handling operations that can sometimes be tricky, like handling errors for undefined properties.

Example:

 

const obj = { name: "Alice" };

// Using Reflect to manipulate properties
Reflect.set(obj, "age", 25);
console.log(Reflect.get(obj, "age")); // 25
console.log(Reflect.has(obj, "name")); // true

 

Reflect methods are often used in conjunction with Proxy to handle these intercepted operations and ensure they behave as expected.

Example: Using Reflect with Proxy :

 

const handler = {
set(target, property, value) {
if (property === "age" && (typeof value !== "number" || value < 0)) {
throw new Error("Age must be a positive number.");
}
return Reflect.set(target, property, value); // Mimics default JS behavior
},

get(target, property) {
if (property in target) {
return Reflect.get(target, property); // Mimics default JS behavior
}
return `Property "${property}" does not exist.`;
}
};

const person = new Proxy({}, handler);

// Setting valid properties
person.name = "Alice";
console.log(person.name); // Alice

// Validating age
person.age = 25;
console.log(person.age); // 25

try {
person.age = -5; // Throws error: Age must be a positive number.
} catch (e) {
console.error(e.message);
}

// Accessing nonexistent properties
console.log(person.address); // Property "address" does not exist.

 

Why Use Reflect in Proxy Traps?

  1. Consistency with JavaScript Defaults:
    • Reflect methods behave identically to JavaScript’s default property operations, including handling edge cases like inherited properties, getters, and setters.
    • Example: Reflect.get respects the prototype chain, just as target[property] would, but ensures you always get consistent behavior.
  2. Clean and Predictable Error Handling:
    • Directly using target[property] or target[property] = value may throw errors for certain operations, like Object.freeze(target). Reflect methods return false instead, making error handling smoother.
  3. Symmetry Between Proxy and Reflect:
    • Using Reflect in Proxy traps creates a more declarative and explicit implementation. It clearly shows you are invoking the default behavior, which is especially useful in larger or shared codebases.
24.

Explain Object.defineProperty() and its purpose.

Answer

Object.defineProperty() defines a new property or modifies an existing property with descriptors like writable, enumerable, and configurable.

Example:

 

const obj = {};
Object.defineProperty(obj, "name", {
value: "Alice",
writable: true,
enumerable: true,
configurable: true
});

// defaults for property descripton:
// { writable: false, enumerable: false, configurable: false }
Object.defineProperty(obj, "age", { value: 18 });


console.log(obj.name); // Alice
console.log(obj.age); // 18

obj.name = "Bob";
obj.age = 21; // No effect ("age" is not writable)
console.log(Object.keys(obj)); // ["name"] ("age" is not enumerable)
delete obj.age; // No effect ("age" is not configurable, hence cannot be deleted)

console.log(obj); // { name: "Bob", age: 18 }
25.

What are Async Iterators in JavaScript?

Answer

Async iterators allow iteration over asynchronous data sources using for await...of. They enable you to iterate through values that may be available at a later time, handling promises within the iteration process.

Unlike regular iterators, async iterators return promises. They are particularly useful when you’re working with asynchronous data, such as reading from a file, querying an API, or waiting for timeouts.

Example:

 

// Async generator simulating async data fetching
async function* fetchData() {
const data = [
Promise.resolve("Hello"),
Promise.resolve("Async"),
Promise.resolve("World")
];

for (const promise of data) {
yield promise;
}
}

(async () => {
for await (const value of fetchData()) {
console.log(value);
}
})();
// Outputs: Hello, Async, World
26.

What is the WeakRef object in JavaScript?

Answer

The WeakRef object allows to create weak references to objects, meaning that the object can be garbage collected if there are no strong references to it. This is useful when we want to hold references to objects (like in caches) without preventing them from being collected when memory is low.

Key Points:

  • A WeakRef does not prevent garbage collection of the object it references.
  • The object can be collected as soon as there are no other strong references to it.
  • The deref() method is used to access the value of the referenced object, but it will return undefined if the object has been garbage collected.

Example:

 

// Creating a weak reference to an object
let obj = { name: "Alice" };
const weakRef = new WeakRef(obj);

// Accessing the object using deref()
console.log(weakRef.deref()); // { name: "Alice" }

// Removing the strong reference to the object
obj = null; // Object becomes eligible for garbage collection

// deref() returns undefined if the object was garbage collected
setTimeout(() => {
console.log(weakRef.deref()); // undefined (object may be garbage collected)
}, 1000);

 

27.

What are optional chaining (?.) and nullish coalescing (??)?

Answer
  1. Optional Chaining (?.):
    • Safely access deeply nested properties without checking each level.

 

const obj = { a: { b: { c: 42 } } };
console.log(obj?.a?.b?.c); // 42
console.log(obj?.x?.y); // undefined

const key = 'b';
console.log(obj?.a?.[key]); // { c: 42 }

 

  1. Nullish Coalescing (??):
    • Provides a default value if the left-hand side is null or undefined.

 

const nullishValue = null;
console.log(nullishValue ?? "Default"); // "Default"

const otherwiseFalsy = 0;
console.log(otherwiseFalsy ?? "Default"); // 0
console.log(otherwiseFalsy || "Default"); // "Default"
28.

What is debouncing and throttling?

Answer

Both debouncing and throttling are techniques used to control the rate at which a function is called. They help optimize performance, especially in scenarios like handling user input or scroll events.

  1. Debouncing: ensures that a function is executed only after a specified delay of inactivity. It prevents multiple invocations within a short time frame, only calling the function after the user stops triggering the event.

 

function debounce(func, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => func(...args), delay);
};
}

 

Use case: Ideal for scenarios like form validation, search input fields, or window resizing, where you want to avoid excessive function calls while the user is actively interacting.

  1. Throttling: ensures that a function is executed at most once in a specified interval, regardless of how many times the event is triggered.

 

function throttle(func, interval) {
let lastCall = 0;
return (...args) => {
const now = Date.now();
if (now - lastCall >= interval) {
lastCall = now;
func(...args);
}
};
}

 

Use case: Ideal for scenarios where you need to limit the number of times an event handler is triggered, such as for scroll or resize events, where you may want to update the UI periodically but not too frequently.

29.

What is the difference between Object.keys(), Object.values(), and Object.entries()?

Answer
Method Description Example
Object.keys() Returns an array of property keys ["a", "b"]
Object.values() Returns an array of property values [1, 2]
Object.entries() Returns an array of key-value pairs [["a", 1], ["b", 2]]

 

Example:

 

const obj = { a: 1, b: 2 };
console.log(Object.keys(obj)); // ["a", "b"]
console.log(Object.values(obj)); // [1, 2]
console.log(Object.entries(obj)); // [["a", 1], ["b", 2]]
30.

How does the event.preventDefault() method work?

Answer

The event.preventDefault() method is used to prevent the default action associated with an event from occurring. This is often used to stop browser actions like form submissions, link redirections, or other default behaviors that the browser performs in response to user interaction.

Key Points:

  • It only affects the default behavior of the event, not the event propagation.
  • It is useful for handling events in custom ways while preventing the default browser behavior (like navigating, submitting a form, etc.).

Example:

 

document.querySelector("form").addEventListener("submit", (e) => {
e.preventDefault(); // Prevents form submission
console.log("Form submission prevented");
});

document.querySelector("a").addEventListener("click", (e) => {
e.preventDefault(); // Prevents navigation to the href link
console.log("Link click prevented");
});

JavaScript Coding Interview Questions

1.

Reverse a String

Answer

Task:

Write a function that takes a string as input and returns the string reversed.

 

// Implement the function to reverse the string
function reverseString(str) {
// Your code here
}

// Example
console.log(reverseString("hello"));

 

Answer:

 

function reverseString(str) {
return str.split('').reverse().join('');
}

// Example
console.log(reverseString("hello")); // Output: "olleh"
2.

Check if a String is a Palindrome

Answer

Task:

Write a function that checks if a given string is a palindrome (reads the same backwards and forwards). The function should return true if it is a palindrome, and false otherwise.

 

// Implement the function to check if a string is a palindrome
function isPalindrome(str) {
// Your code here
}

// Examples
console.log(isPalindrome("racecar"));
console.log(isPalindrome("hello"));

 

Answer:

 

function isPalindrome(str) {
const reversed = str.split('').reverse().join('');
return str === reversed;
}

// Examples
console.log(isPalindrome("racecar")); // Output: true
console.log(isPalindrome("hello")); // Output: false
3.

Check if a String is a Valid Palindrome (ignoring non-alphanumeric)

Answer

Task:

Write a function that checks if a given string is a palindrome, considering only alphanumeric characters and ignoring cases.

 

// Implement the function to check for a valid palindrome
function isValidPalindrome(s) {
// Your code here
}

// Examples
console.log(isValidPalindrome("A man, a plan, a canal: Panama"));
console.log(isValidPalindrome("race a car"));

 

Answer:

 

function isValidPalindrome(s) {
    // Remove non-alphanumeric characters and convert to lowercase
    const sanitized = s.toLowerCase().replace(/[^a-z0-9]/g, '');


// DRY and use the previously created logic ;)
    return isPalindrome(sanitized)
}


function isPalindrome(str) {
    const reversed = str.split('').reverse().join('');
    return str === reversed;
}


// Examples
console.log(isValidPalindrome("A man, a plan, a canal: Panama")); // Output: true
console.log(isValidPalindrome("race a car"));                     // Output: false
4.

Find the Largest Number in an Array

Answer

Task:

Write a function that takes an array of numbers and returns the largest number.

 

// Implement the function to find the largest number in an array
function findLargest(arr) {
// Your code here
}

// Example
console.log(findLargest([1, 5, 3, 9]));

 

Answer:

 

function findLargest(arr) {
return Math.max(...arr);
}

// Example
console.log(findLargest([1, 5, 3, 9])); // Output: 9
5.

Implement FizzBuzz

Answer

Task:

Write a function that prints numbers from 1 to n. For multiples of three, print "Fizz" instead of the number, and for multiples of five, print "Buzz". For numbers which are multiples of both three and five, print "FizzBuzz".

 

// Implement the function to print FizzBuzz up to n
function fizzBuzz(n) {
// Your code here
}

// Example
fizzBuzz(16);

 

Answer:

 

function fizzBuzz(n) {
for (let i = 1; i <= n; i++) {
if (i % 15 === 0) {
console.log("FizzBuzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else {
console.log(i);
}
}
}

// Example
fizzBuzz(16);
// Output:
// 1
// 2
// Fizz
// 4
// Buzz
// Fizz
// 7
// 8
// Fizz
// Buzz
// 11
// Fizz
// 13
// 14
// FizzBuzz
// 16
6.

Flatten a Nested Array

Answer

Task:

Write a function that takes a nested array and returns a single, flat array with all the elements.

 

// Implement the function to flatten a nested array
function flattenArray(arr) {
// Your code here
}

// Example
console.log(flattenArray([1, [2, [3, 4]], 5]));

 

Answer:

 

function flattenArray(arr) {
return arr.flat(Infinity);
}

// Example
console.log(flattenArray([1, [2, [3, 4]], 5])); // Output: [1, 2, 3, 4, 5]
7.

Remove Duplicates from an Array

Answer

Task:

Write a function that removes duplicate values from an array.

 

// Implement the function to remove duplicates from an array
function removeDuplicates(arr) {
// Your code here
}

// Example
console.log(removeDuplicates([1, 2, 2, 3, 4, 4]));

 

Answer:

 

function removeDuplicates(arr) {
return [...new Set(arr)];
}

// Example
console.log(removeDuplicates([1, 2, 2, 3, 4, 4])); // Output: [1, 2, 3, 4]
8.

Find the Factorial of a Number

Answer

Task:

Write a function that calculates the factorial of a non-negative integer n.

 

// Implement the function to calculate the factorial of a number
function factorial(n) {
// Your code here
}

// Examples
console.log(factorial(5));
console.log(factorial(0));

 

Answer:

 

function factorial(n) {
if (n === 0) return 1;
return n * factorial(n - 1);
}

// Examples
console.log(factorial(5)); // Output: 120
console.log(factorial(0)); // Output: 1
9.

Merge Two Sorted Arrays

Answer

Task:

Write a function that merges two sorted arrays into a single sorted array.

 

// Implement the function to merge two sorted arrays
function mergeSortedArrays(arr1, arr2) {
// Your code here
}

// Example
console.log(mergeSortedArrays([1, 3, 5], [2, 4, 6]));

 

Answer:

 

// Answer
function mergeSortedArrays(arr1, arr2) {
let merged = [];
let i = 0, j = 0;

// Merge arrays until one is exhausted
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
merged.push(arr1[i++]);
} else {
merged.push(arr2[j++]);
}
}

// Concatenate any remaining elements
return merged.concat(arr1.slice(i)).concat(arr2.slice(j));
}

// Example
console.log(mergeSortedArrays([1, 3, 5], [2, 4, 6])); // Output: [1, 2, 3, 4, 5, 6]
10.

Count the Frequency of Elements in an Array

Answer

Task:

Write a function that counts the occurrences of each element in an array and returns an object with elements as keys and their counts as values.

 

// Implement the function to count the frequency of elements
function countFrequency(arr) {
// Your code here
}

// Example
console.log(countFrequency([1, 2, 3, 3, 2, 3]));
console.log(countFrequency(["Alice", "Bob", "Claire", "Claire", "Bob", "Claire"]));

 

Answer:

 

function countFrequency(arr) {
return arr.reduce((res, item) => {
res[item] = (res[item] || 0) + 1;
return res;
}, {});
}

// Example
console.log(countFrequency([1, 2, 2, 3, 3, 3]));
// Output: { '1': 1, '2': 2, '3': 3 }
console.log(countFrequency(["Alice", "Bob", "Claire", "Claire", "Bob", "Claire"]));
// Output: { 'Alice': 1, 'Bob': 2, 'Claire': 3 }
11.

Find the First Non-Repeating Character

Answer

Task:

Write a function that finds the first character in a string that does not repeat and returns it. If all characters repeat, return null.

 

// Implement the function to find the first non-repeating character
function firstNonRepeatingChar(str) {
// Your code here
}

// Example
console.log(firstNonRepeatingChar("swiss"));
console.log(firstNonRepeatingChar("aabbcc"));

 

Answer:

 

function firstNonRepeatingChar(str) {
for (const char of str) {
if (str.indexOf(char) === str.lastIndexOf(char)) {
return char; // Return the first non-repeating character
}
}
return null; // If no non-repeating character is found
}

// Example
console.log(firstNonRepeatingChar("swiss")); // Output: "w"
console.log(firstNonRepeatingChar("aabbcc")); // Output: null
console.log(firstNonRepeatingChar("abcabcde")); // Output: "d"

 

Note: Using indexOf and lastIndexOf comparison looks quick and elegant, but might lead to O(n²) time complexity for very long strings, because indexOf and lastIndexOf each perform linear scans over the string for every character.

Another option:

 

function firstNonRepeatingChar(str) {
const charCount = new Map();

// count occurrences
for (const char of str) {
charCount.set(char, (charCount.get(char) || 0) + 1);
}

// convert Map to an array of entries and find the first character with count 1
return [...charCount].find(([char, count]) => count === 1)?.[0] ?? null;
}

// Example
console.log(1, firstNonRepeatingChar("swiss")); // Output: "w"
console.log(2, firstNonRepeatingChar("aabbcc")); // Output: null
console.log(3, firstNonRepeatingChar("abcabcde")); // Output: "d"
console.log(4, firstNonRepeatingChar("abc")); // Output: "a"

 

This approach has O(n) time complexity. The string is traversed once to count occurrences, and then a second pass over the Map entries is made (which is proportional to the number of unique characters, so it’s still O(n)).

Additionally, we’re using a Map, instead of a plain object ({}), because in Map the order of entries is guaranteed to be the order of insertion.

12.

Check if Two Strings Are Anagrams

Answer

Task:

Write a function to determine if two strings are anagrams of each other. Two strings are anagrams if they contain the same characters in a different order.

 

// Implement the function to check for anagrams
function areAnagrams(str1, str2) {
// Your code here
}

// Examples
console.log(areAnagrams("listen", "silent"));
console.log(areAnagrams("hello", "world"));

 

Answer:

 

function areAnagrams(str1, str2) {
const normalize = (str) => str.toLowerCase().split('').sort().join('');
return normalize(str1) === normalize(str2);
}

// Examples
console.log(areAnagrams("listen", "silent")); // Output: true
console.log(areAnagrams("hello", "world")); // Output: false
13.

Implement Binary Search

Answer

Task:

Write a function that performs a binary search on a sorted array and returns the index of the target element. If the target is not found, return -1.

 

// Implement the binary search function
function binarySearch(arr, target) {
// Your code here
}

// Example
console.log(binarySearch([1, 2, 3, 4, 5], 3));
console.log(binarySearch([1, 2, 3, 4, 5], 6));

 

Answer:

 

function binarySearch(arr, target) {
let left = 0; // Start of the array
let right = arr.length - 1; // End of the array

// Keep looping as long as the search space is valid (left <= right)
while (left <= right) {
const mid = Math.floor((left + right) / 2); // Find middle index

if (arr[mid] === target) {
return mid; // If found, return the index of the target
} else if (arr[mid] < target) {
left = mid + 1; // Narrow search to the right half
} else {
right = mid - 1; // Narrow search to the left half
}
}

return -1; // Target not found
}


// Example
console.log(binarySearch([1, 2, 3, 4, 5], 3)); // Output: 2
console.log(binarySearch([1, 2, 3, 4, 5], 6)); // Output: -1
14.

Find the Maximum Subarray Sum (Kadane’s Algorithm)

Answer

Task:

Write a function to find the contiguous subarray within a one-dimensional array of numbers that has the largest sum.

 

// Implement the function to find the maximum subarray sum
function maxSubarraySum(arr) {
// Your code here
}

// Example
console.log(maxSubarraySum([-2, 1, -3, 4, -1, 2, 1, -5, 4]));

 

Answer:

 

function maxSubarraySum(arr) {
let maxSum = arr[0]; // Initialize the global max sum with the first element
let currentSum = arr[0]; // Initialize current sum with the first element

for(let i = 1; i < arr.length; i++) {
// Update current sum:
// either extend the previous subarray or start a new one
currentSum = Math.max(arr[i], currentSum + arr[i]);

// Update max sum if we have found a new higher sum
maxSum = Math.max(maxSum, currentSum);
}

return maxSum; // Return the maximum subarray sum
}

// Example
console.log(maxSubarraySum([-2, 1, -3, 4, -1, 2, 1, -5, 4])); // Output: 6
15.

Rotate an Array

Answer

Task:

Write a function that rotates an array to the right by k steps.

 

// Implement the function to rotate the array
function rotateArray(arr, k) {
// Your code here
}

// Example
console.log(rotateArray([1, 2, 3, 4, 5], 2));

 

Answer:

 

function rotateArray(arr, k) {
k = k % arr.length; // Ensure k is within the bounds of the array length
return arr.slice(-k).concat(arr.slice(0, -k));
}

// Example
console.log(rotateArray([1, 2, 3, 4, 5], 2)); // Output: [4, 5, 1, 2, 3]
16.

Find Missing Number in an Array

Answer

Task:

Given an array containing n - 1 numbers taken from the range 1 to n, find the missing number.

 

// Implement the function to find the missing number
function findMissingNumber(arr, n) {
// Your code here
}

// Example
console.log(findMissingNumber([1, 2, 4, 5, 6], 6));

 

Answer:

 

function findMissingNumber(arr, n) {
const total = (n * (n + 1)) / 2;
const sum = arr.reduce((acc, num) => acc + num, 0);
return total - sum;
}

// Example
console.log(findMissingNumber([1, 2, 4, 5, 6], 6)); // Output: 3
console.log(findMissingNumber([1, 2, 3, 4, 5], 6)); // Output: 6
17.

Check if a Number is Prime

Answer

Task:

Write a function to check if a given number is prime.

 

// Implement the function to check for a prime number
function isPrime(n) {
// Your code here
}

// Examples
console.log(isPrime(7));
console.log(isPrime(10));

 

Answer:

 

function isPrime(n) {
if (n <= 1) return false;

for(let i = 2; i <= Math.sqrt(n); i++) {
if(n % i === 0) return false;
}

return true;
}

// Examples
console.log(isPrime(7)); // Output: true
console.log(isPrime(10)); // Output: false

 

Optimization: Instead of checking all numbers up to n - 1, we only check up to sqrt(n). This reduces the number of checks and makes the algorithm more efficient.

Why? A number n can only have factors less than or equal to sqrt(n) and greater than or equal to sqrt(n). For example, if n = 36, the factors are 1, 2, 3, 4, 6, 9, 12, 18, 36. Notice that 6 is the square root of 36, and we don’t need to check beyond 6 because any factor larger than 6 would have already been paired with a smaller factor.

18.

Find the Intersection of Two Arrays

Answer

Task:

Write a function that returns the intersection of two arrays.

 

// Implement the function to find the intersection
function intersection(arr1, arr2) {
// Your code here
}

// Example
console.log(intersection([1, 2, 3], [2, 3, 4]));

 

Answer:

 

function intersection(arr1, arr2) {
const set2 = new Set(arr2);

return arr1.filter(item => set2.has(item));
}

// Example
console.log(intersection([1, 2, 3], [2, 3, 4])); // Output: [2, 3]
19.

Check if a String Contains Balanced Parentheses

Answer

Task:

Write a function that checks if a string contains balanced parentheses ().

 

// Implement the function to check for balanced parentheses
function isBalanced(str) {
// Your code here
}

// Examples
console.log(isBalanced("((goodbye))"));
console.log(isBalanced("((cruel)"));
console.log(isBalanced("(world))"));

 

Answer:

 

function isBalanced(str) {
let count = 0;

for (const char of str) {
if (char === '(') count++;
else if (char === ')') count--;

// If count goes negative, we have an unmatched closing parenthesis
if (count < 0) return false;
}

return count === 0; // If count is zero, all parentheses are balanced
}

// Examples
console.log(isBalanced("((goodbye))")); // Output: true
console.log(isBalanced("((cruel)")); // Output: false
console.log(isBalanced("(world))")); // Output: false
20.

Implement Merge Sort Algorithm

Answer

Task:

Write a function that implements the merge sort algorithm to sort an array of numbers in ascending order.

 

// Implement the mergeSort function
function mergeSort(arr) {
// Your code here
}

// Example
console.log(mergeSort([5, 2, 9, 1, 5, 6]));

 

Answer:

 

function mergeSort(arr) {
if (arr.length <= 1) return arr;

const middle = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, middle));
const right = mergeSort(arr.slice(middle));

return merge(left, right);
}

function merge(left, right) {
const result = [];
let i = 0;
let j = 0;

// Merge the two arrays while comparing their elements
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
result.push(left[i++]);
} else {
result.push(right[j++]);
}
}

// Concatenate any remaining elements
return result.concat(left.slice(i)).concat(right.slice(j));
}

// Example
console.log(mergeSort([5, 2, 9, 1, 5, 6])); // Output: [1, 2, 5, 5, 6, 9]
21.

Find the Longest Increasing Subsequence

Answer

Task:

Write a function that finds the length of the longest increasing subsequence in an array of numbers.

 

// Implement the function to find the longest increasing subsequence
function lengthOfLIS(nums) {
// Your code here
}

// Example
console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18]));

 

Answer:

 

function lengthOfLIS(nums) {
if (!nums.length) return 0;
const dp = Array(nums.length).fill(1);

// Build the dp array where dp[i] represents the length of the longest
// increasing subsequence ending with nums[i]
for (let i = 1; i < nums.length; i++) {
for (let j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}

// The maximum value in dp array is the result
return Math.max(...dp);
}

// Example
console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18])); // Output: 4
// The LIS is: [2, 3, 7, 101]
22.

Compute the nth Fibonacci Number Using Memoization

Answer

Task:

Write a function that computes the nth Fibonacci number using memoization to optimize performance.

 

// Implement the memoized Fibonacci function
function fibonacci(n, memo = {}) {
// Your code here
}

// Example
console.log(fibonacci(50));

 

Answer:

 

function fibonacci(n, memo = {}) {
// Base cases
if (n <= 1) return n;

// Check if result is already computed
if (memo[n]) return memo[n];

// Recursively compute with memoization
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);

return memo[n];
}

// Example
console.log(fibonacci(50)); // Output: 12586269025
23.

Implement a Debounce Function

Answer

Task:

Write a debounce function that delays the execution of a function until after a specified wait time has elapsed since the last time it was invoked.

 

// Implement the debounce function
function debounce(func, delay) {
// Your code here
}

// Example usage
const debouncedLog = debounce(() => console.log("Debounced!"), 300);
debouncedLog();
debouncedLog();
debouncedLog();
// "Debounced!" should be logged once after 300ms

 

Answer:

 

function debounce(func, delay) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
}

// Example usage
const debouncedLog = debounce(() => console.log("Debounced!"), 300);
debouncedLog();
debouncedLog();
debouncedLog();
// "Debounced!" will be logged once after 300ms
24.

Implement a Throttle Function

Answer

Task:

Write a throttle function that ensures a function is called at most once in a specified time interval.

 

// Implement the throttle function
function throttle(func, interval) {
// Your code here
}

// Example usage
const throttledLog = throttle(() => console.log("Throttled!"), 500);
throttledLog();
throttledLog();
throttledLog();
// "Throttled!" should be logged immediately and then ignored for the next 500ms

 

Answer:

 

function throttle(func, interval) {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
func(...args);
}
};
}

// Example usage
const throttledLog = throttle(() => console.log("Throttled!"), 500);
throttledLog(); // Logs immediately
throttledLog(); // Ignored
throttledLog(); // Ignored
25.

Check if a Binary Tree is Symmetric

Answer

Task:

Write a function that checks if a binary tree is symmetric around its center.

 

// Implement the function to check if a binary tree is symmetric
function isSymmetric(root) {
// Your code here
}

// Example binary tree
const tree = {
value: 1,
left: {
value: 2,
left: { value: 3, left: null, right: null },
right: { value: 4, left: null, right: null },
},
right: {
value: 2,
left: { value: 4, left: null, right: null },
right: { value: 3, left: null, right: null },
},
};

console.log(isSymmetric(tree));

 

Answer:

 

function isSymmetric(root) {
if (!root) return true;

function isMirror(left, right) {
if (!left && !right) return true;
if (!left || !right) return false;

return (
left.value === right.value &&
isMirror(left.left, right.right) &&
isMirror(left.right, right.left)
);
}

return isMirror(root.left, root.right);
}

// Example
console.log(isSymmetric(tree)); // Output: true
26.

Perform a Deep Comparison Between Two Objects

Answer

Task:

Write a function that performs a deep comparison between two objects to determine if they are equal.

 

// Implement the function for deep object comparison
function deepEqual(obj1, obj2) {
// Your code here
}

// Examples
const objA = { a: 1, b: { c: 2 } };
const objB = { a: 1, b: { c: 2 } };
const objC = { a: 1, b: { c: 3 } };

console.log(deepEqual(objA, objB)); // Should return true
console.log(deepEqual(objA, objC)); // Should return false

 

Answer:

 

function deepEqual(obj1, obj2) {
// Check for strict equality
if (obj1 === obj2) return true;

// Check for null or non-object types
if (
obj1 == null ||
typeof obj1 !== 'object' ||
obj2 == null ||
typeof obj2 !== 'object'
) {
return false;
}

// Get object keys
const keysA = Object.keys(obj1);
const keysB = Object.keys(obj2);

// Check if number of keys are different
if (keysA.length !== keysB.length) return false;

// Check if both objects have the same keys
for (const key of keysA) {
if (!keysB.includes(key)) {
return false; // Early return if keys are different
}
}

// Recursively check each key
for (const key of keysA) {
if (!deepEqual(obj1[key], obj2[key])) {
return false;
}
}

return true;
}

// Examples
console.log(deepEqual(objA, objB)); // Output: true
console.log(deepEqual(objA, objC)); // Output: false
27.

Perform a Breadth-First Search (BFS) on a Graph

Answer

Task:

Write a function that performs a breadth-first search (BFS) on a graph and returns the nodes in the order they were visited.

 

// Implement the BFS function
function bfs(graph, startNode) {
// Your code here
}

// Example graph represented as an adjacency list
const graph = {
A: ['B', 'C'],
B: ['A', 'D', 'E'],
C: ['A', 'F'],
D: ['B'],
E: ['B', 'F'],
F: ['C', 'E'],
};

console.log(bfs(graph, 'A'));

 

Answer:

 

function bfs(graph, startNode) {
const visited = [];
const queue = [startNode];
const seen = new Set();

while (queue.length > 0) {
const node = queue.shift();

if (!seen.has(node)) {
visited.push(node);

seen.add(node);

queue.push(...graph[node]);
}
}

return visited;
}

console.log(bfs(graph, 'A')); // Output: ['A', 'B', 'C', 'D', 'E', 'F']
28.

Implement QuickSort Algorithm

Answer

Task:

Write a function that implements the quicksort algorithm to sort an array of numbers in ascending order.

 

// Implement the quickSort function
function quickSort(arr) {
// Your code here
}

// Example
console.log(quickSort([5, 2, 9, 1, 5, 6]));

 

Answer:

 

function quickSort(arr) {
if (arr.length <= 1) return arr;

const pivot = arr[arr.length - 1];
const left = [];
const right = [];

// Partition the array into left and right subarrays
for (const num of arr.slice(0, arr.length - 1)) {
if (num < pivot) left.push(num);
else right.push(num);
}

// Recursively sort the subarrays and concatenate
return [...quickSort(left), pivot, ...quickSort(right)];
}

// Example
console.log(quickSort([5, 2, 9, 1, 5, 6])); // Output: [1, 2, 5, 5, 6, 9]
29.

Check if a Number is an Armstrong Number

Answer

Task:

Write a function that checks if a given number is an Armstrong number. An Armstrong number is an n-digit number that is equal to the sum of its digits raised to the nth power.

 

// Implement the function to check for an Armstrong number
function isArmstrongNumber(num) {
// Your code here
}

// Examples
console.log(isArmstrongNumber(153)); // Should give true
console.log(isArmstrongNumber(123)); // Should give false

 

Answer:

 

function isArmstrongNumber(num) {
const digits = num.toString().split('');
const n = digits.length;
const sum = digits.reduce((acc, digit) => acc + Math.pow(Number(digit), n), 0);

return num === sum;
}

// Examples
console.log(isArmstrongNumber(153)); // Output: true
console.log(isArmstrongNumber(123)); // Output: false
30.

Find All Permutations of a String

Answer

Task:

Write a function that returns all permutations of a given string.

 

// Implement the function to find all permutations of a string
function getPermutations(str) {
// Your code here
}

// Example
console.log(getPermutations('abc'));

 

Answer:

 

function getPermutations(str) {
const results = [];

if (str.length === 1) {
results.push(str);
return results;
}

// Iterate over the string and recursively find permutations
for (let i = 0; i < str.length; i++) {
const firstChar = str[i];
const charsLeft = str.slice(0, i) + str.slice(i + 1);
const innerPermutations = getPermutations(charsLeft);

for (const permutation of innerPermutations) {
results.push(firstChar + permutation);
}
}

return results;
}

// Example
console.log(getPermutations('abc')); // Output: ["abc", "acb", "bac", "bca", "cab", "cba"]
JavaScript Developer hiring resources
Hire JavaScript Developers
Hire fast and on budget—place a request, interview 1-3 curated developers, and get the best one onboarded by next Friday. Full-time or part-time, with optimal overlap.
Hire now
Q&A about hiring JavaScript Developers
Want to know more about hiring JavaScript Developers? Lemon.io got you covered
Read Q&A
JavaScript Developer Job Description Template
Attract top JavaScript developers with a clear, compelling job description. Use our expert template to save time and get high-quality applicants fast.
Check the Job Description

Hire remote JavaScript developers

Developers who got their wings at:
Testimonials
star star star star star
Gotta drop in here for some Kudos. I’m 2 weeks into working with a super legit dev on a critical project, and he’s meeting every expectation so far 👏
avatar
Francis Harrington
Founder at ProCloud Consulting, US
star star star star star
I recommend Lemon to anyone looking for top-quality engineering talent. We previously worked with TopTal and many others, but Lemon gives us consistently incredible candidates.
avatar
Allie Fleder
Co-Founder & COO at SimplyWise, US
star star star star star
I've worked with some incredible devs in my career, but the experience I am having with my dev through Lemon.io is so 🔥. I feel invincible as a founder. So thankful to you and the team!
avatar
Michele Serro
Founder of Doorsteps.co.uk, UK

Simplify your hiring process with remote JavaScript developers

Popular JavaScript Development questions

What is the impact of JavaScript frameworks on SEO?

JavaScript frameworks affect SEO in ways that depend on how well search engines crawl and index dynamically generated content. For example, to offsite this, React developers must make use of server-side rendering libraries like Next.js and Nuxt.js of Vue.js. This is because, for one, SSR pre-renders the HTML on the server before it sends it to the client, hence making sure your content can get indexed, which will drive a better SEO performance of your site.

How does JavaScript handle cross-browser compatibility?

Feature detection and polyfills, or even transpilers like Babel, are means to handle cross-browser compatibility in JavaScript. Feature detection checks with the browser to see whether or not it supports a certain feature, which one could then use. Polyfills fill in the implementation for features that might not natively support an older browser. Transpilers like Babel convert new JavaScript into backward-compatible versions that could run on older browsers

What are JavaScript modules, and why are they useful?

JavaScript modules allow developers to break down their code into reusable, self-contained units. Modules, starting in ES6, now enable developers to organize code in smaller-sized files which can be imported and exported according to need, giving modularity and even maintainability. This reduces the chance of naming collision and, moreover, makes the management of large codebases easier because dependencies are well-defined.

How does JavaScript interact with APIs?

It can use Fetch API or XMLHttpRequest to communicate with APIs, send, and fetch data in many formats that range from JSON to XML from web servers. The JavaScript dynamically integrates this information into the web page. Because of this interaction, hence, it can build dynamic web applications refreshing the content without needing to reload the whole web page for a better user experience.

What exactly is JavaScript used for?

JavaScript is utilized mainly to impart interactivity and dynamic behavior in websites. Some examples include form validation, animations, maps with interactive elements, and real-time content updates. These involve server-side development using Node.js, mobile app development using frameworks such as React Native, and even desktop application development, hence versatile in that it can be both a Back-end and Front-end language.

image

Ready-to-interview vetted JavaScript developers are waiting for your request