Top 40 JavaScript Interview Questions For 5 Years Of Experience

Top 40 JavaScript Interview Questions For 5 Years Of Experience

1. What do you understand about JavaScript?

JavaScript is a versatile and powerful programming language primarily used for front-end web development but also increasingly popular for back-end development and other types of applications. Here’s a brief overview of what JavaScript entails:

Client-Side Scripting: JavaScript is primarily known for its role in client-side scripting, where it runs in the browser and enables interactive and dynamic web content. It allows developers to manipulate HTML, CSS, and the Document Object Model (DOM) to create dynamic user interfaces, handle user interactions, and perform asynchronous operations like fetching data from servers.

Dynamic Typing: JavaScript is a dynamically typed language, meaning variable types are determined at runtime rather than explicitly declared. This allows for flexibility but can also lead to unexpected behavior if not handled carefully.

Event-Driven Programming: JavaScript is event-driven, meaning it responds to events triggered by user interactions (e.g., clicks, keystrokes) or by the browser environment (e.g., page load, network requests). Event-driven programming is fundamental to building interactive web applications.

Asynchronous Programming: JavaScript supports asynchronous programming through mechanisms like callbacks, promises, and async/await. Asynchronous operations allow JavaScript to perform tasks such as fetching data from servers or interacting with databases without blocking the main execution thread, improving responsiveness and performance.

Cross-Platform Development: With the rise of frameworks like Node.js, JavaScript can now be used for server-side development, enabling developers to build full-stack applications entirely in JavaScript. This allows for code reuse and a unified development experience across client and server environments.

Ecosystem and Libraries: JavaScript has a vast ecosystem of libraries and frameworks that extend its capabilities and simplify common tasks. Popular front-end frameworks like React, Angular, and Vue.js provide tools for building scalable and maintainable user interfaces, while back-end frameworks like Express.js and NestJS facilitate server-side development.

Community and Support: JavaScript has one of the largest and most active developer communities, with abundant resources, tutorials, forums, and documentation available. This vibrant community contributes to the continuous evolution of the language and the development of new tools and technologies.

In summary, JavaScript is a versatile programming language that powers the modern web, enabling developers to build interactive, responsive, and feature-rich web applications across client and server environments. Its flexibility, ease of use, and extensive ecosystem make it a popular choice for developers worldwide.

2. What are data types in JavaScript?

Certainly! JavaScript supports several data types, which can be categorized into two main categories: primitive data types and non-primitive (reference) data types. Here’s an overview of each:

Primitive Data Types:

  1. Number: Represents both integer and floating-point numbers. Examples: 42, 3.14.
  2. String: Represents a sequence of characters enclosed within single (‘ ‘) or double (” “) quotes. Examples: 'Hello', "JavaScript".
  3. Boolean: Represents a logical value indicating true or false. Examples: true, false.
  4. Undefined: Represents a variable that has been declared but not assigned a value. Example: let x;.
  5. Null: Represents an intentional absence of any value. Example: let y = null;.
  6. Symbol (ES6+): Represents a unique and immutable value, often used as object property keys. Example: const sym = Symbol('foo');.

Non-Primitive (Reference) Data Types:

  1. Object: Represents a collection of key-value pairs, where values can be of any data type, including other objects. Examples: const person = { name: 'John', age: 30 };.
  2. Array: Represents a special type of object used to store multiple values in a single variable. Example: const numbers = [1, 2, 3, 4, 5];.
  3. Function: Represents a reusable block of code that can be invoked by name. Functions are also objects in JavaScript. Example:function greet(name) { console.log('Hello, ' + name + '!'); }
  4. Date: Represents a specific moment in time, stored as the number of milliseconds since January 1, 1970, 00:00:00 UTC. Example: const today = new Date();.
  5. RegExp: Represents a regular expression object used for pattern matching within strings. Example: const regex = /[a-z]+/;.
  6. Others: JavaScript also provides other non-primitive data types like Map, Set, and WeakMap, which are introduced in ES6 and are used for specific data manipulation purposes.

Understanding these data types is fundamental to working with JavaScript effectively, as they form the basis for all data manipulation and processing in the language.

3. What are features of JavaScript?

JavaScript is a versatile and dynamic programming language that powers much of the interactivity on the web. Here are some key features of JavaScript:

  1. High-level language: JavaScript is a high-level programming language, meaning it is designed to be easy for humans to read and write.
  2. Interpreted: JavaScript code is executed line by line (interpreted) by the JavaScript engine in web browsers or other environments, without the need for compilation.
  3. Dynamic typing: JavaScript uses dynamic typing, allowing variables to hold values of any data type without explicit declaration.
  4. Prototype-based object-oriented: JavaScript follows a prototype-based object-oriented programming model, where objects inherit properties and methods from other objects through prototype chains.
  5. Functional programming support: JavaScript supports functional programming paradigms, allowing functions to be treated as first-class citizens, enabling features like higher-order functions and closures.
  6. Event-driven programming: JavaScript is well-suited for event-driven programming, allowing developers to respond to user actions or system events asynchronously.
  7. Asynchronous programming: JavaScript supports asynchronous programming through mechanisms like callbacks, promises, and async/await, enabling non-blocking execution of code.
  8. Cross-platform compatibility: JavaScript can run on various platforms, including web browsers, servers (Node.js), desktop applications, and mobile applications (React Native, NativeScript), making it a versatile choice for software development.
  9. Client-side scripting: JavaScript is primarily used for client-side scripting in web development, enabling dynamic and interactive web pages.
  10. Rich ecosystem: JavaScript has a rich ecosystem of libraries (e.g., jQuery, React, Vue.js), frameworks (e.g., Angular, Express.js), and tools (e.g., Babel, Webpack) that extend its capabilities and simplify development tasks.
  11. Modern language features: JavaScript continues to evolve with regular updates to the ECMAScript specification, introducing new language features and improvements (e.g., ES6, ES7, ES8, ESNext).
  12. Community support: JavaScript has a large and active community of developers, providing resources, documentation, tutorials, and support through forums, communities, and open-source contributions.

These features contribute to JavaScript’s popularity and widespread use in web development, server-side programming, mobile app development, and beyond.

4. How to create an object in JavaScript?

Creating an object in JavaScript can be done using several methods. Here are some common ways to create objects:

Object Literal: This is the simplest way to create an object in JavaScript, using curly braces {} to define key-value pairs.

const person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
greet: function() {
console.log('Hello, ' + this.firstName + ' ' + this.lastName + '!');
}
};

person.greet(); // Outputs: Hello, John Doe!

Constructor Function: You can define a constructor function and create objects using the new keyword.

function Person(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.greet = function() {
        console.log('Hello, ' + this.firstName + ' ' + this.lastName + '!');
    };
}

const person = new Person('John', 'Doe', 30);
person.greet(); // Outputs: Hello, John Doe!

Object.create(): You can create an object with a specified prototype object.

const personPrototype = {
    greet: function() {
        console.log('Hello, ' + this.firstName + ' ' + this.lastName + '!');
    }
};

const person = Object.create(personPrototype);
person.firstName = 'John';
person.lastName = 'Doe';
person.age = 30;

person.greet(); // Outputs: Hello, John Doe!

Class Syntax (ES6+): With ES6, JavaScript introduced class syntax for defining objects.

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    greet() {
        console.log(`Hello, ${this.firstName} ${this.lastName}!`);
    }
}

const person = new Person('John', 'Doe', 30);
person.greet(); // Outputs: Hello, John Doe!

These are some of the common ways to create objects in JavaScript, each with its own advantages and use cases.

5. How to create an array in JavaScript?

Creating an array in JavaScript is straightforward. You can define an array using square brackets [] and populate it with elements. Here are some examples:

Empty Array:

const emptyArray = [];

Array with Elements:

const numbers = [1, 2, 3, 4, 5];
const fruits = ['apple', 'banana', 'orange'];
const mixedArray = [1, 'two', true, { key: 'value' }];

Array Constructor:

const numbers = new Array(1, 2, 3, 4, 5);
const emptyArray = new Array(); // creates an empty array

Array with Specified Length:

const fixedSizeArray = new Array(10); // creates an array with length 10, but no elements

Array with Initial Value:

const filledArray = new Array(5).fill(0); // creates an array with 5 elements, all initialized to 0

Using Array.from() (ES6+):

const numbers = Array.from([1, 2, 3, 4, 5]);

Arrays in JavaScript are versatile and can hold elements of any data type, including numbers, strings, objects, and even other arrays. They also support dynamic resizing, allowing you to add or remove elements as needed.

7. Explain built-in methods in JavaScript?

JavaScript provides a wide range of built-in methods that are available on various data types such as strings, arrays, objects, numbers, and more. Here’s an overview of some commonly used built-in methods:

String Methods:

  1. charAt(): Returns the character at the specified index of a string.
  2. concat(): Concatenates two or more strings.
  3. indexOf(): Returns the index within the calling string of the first occurrence of the specified value.
  4. slice(): Extracts a section of a string and returns it as a new string.
  5. split(): Splits a string into an array of substrings based on a specified separator.
  6. toLowerCase() / toUpperCase(): Converts a string to lowercase / uppercase.
  7. trim(): Removes whitespace from both ends of a string.

Array Methods:

  1. push() / pop(): Adds/removes elements to/from the end of an array.
  2. shift() / unshift(): Adds/removes elements to/from the beginning of an array.
  3. concat(): Returns a new array by combining the array with other arrays or values.
  4. slice(): Extracts a section of an array and returns it as a new array.
  5. join(): Joins all elements of an array into a string.
  6. indexOf() / lastIndexOf(): Returns the index of the first/last occurrence of a specified value in an array.
  7. forEach() / map(): Executes a provided function once for each array element.
  8. filter(): Creates a new array with elements that pass a test.
  9. reduce() / reduceRight(): Applies a function against an accumulator and each value of the array (from left-to-right / right-to-left) to reduce it to a single value.

Object Methods:

  1. Object.keys() / Object.values() / Object.entries(): Returns an array of a given object’s own enumerable property names / values / key-value pairs.
  2. Object.assign(): Copies the values of all enumerable own properties from one or more source objects to a target object.
  3. Object.hasOwnProperty(): Returns a boolean indicating whether the object has the specified property as its own property.
  4. Object.freeze() / Object.seal(): Freezes/seals an object, preventing new properties from being added and existing properties from being removed or changed.

Number Methods:

  1. toFixed(): Formats a number with a fixed number of digits after the decimal point.
  2. toString(): Converts a number to a string.
  3. parseInt() / parseFloat(): Parses a string and returns an integer / floating-point number.

These are just a few examples of the many built-in methods available in JavaScript. Understanding and utilizing these methods can greatly simplify and enhance your JavaScript programming experience.

8. Explain scopes of a variable in JavaScript?

In JavaScript, the scope of a variable determines where in your code that variable is accessible. There are mainly three types of scopes in JavaScript:

Global Scope: Variables declared outside of any function or block have global scope. They can be accessed from anywhere in the code, including inside functions and blocks.

const globalVariable = 'I am global'; function myFunction() { console.log(globalVariable); // Accessible } myFunction(); // Outputs: I am global

Function Scope: Variables declared inside a function have function scope. They are accessible only within the function in which they are declared.

function myFunction() { const functionVariable = 'I am local'; console.log(functionVariable); // Accessible } myFunction(); // Outputs: I am local console.log(functionVariable); // Error: functionVariable is not defined

Block Scope (Introduced in ES6): Variables declared with let and const keywords have block scope. Block scope means the variable is only accessible within the block (i.e., between curly braces {}) where it is defined.

if (true) {
const blockVariable = ‘I am block-scoped’;
console.log(blockVariable); // Accessible } console.log(blockVariable); // Error: blockVariable is not defined

Note: var declarations have function scope, not block scope. This means var variables are accessible throughout the entire function, even outside of blocks.

function myFunction() {
if (true) {
var varVariable = ‘I am function-scoped’;
console.log(varVariable); // Accessible } console.log(varVariable); // Accessible } myFunction(); // Outputs: I am function-scoped

Understanding variable scope is crucial for writing clean and maintainable code, as it helps prevent naming conflicts and unintended variable access.

9. Describe ‘this’ keyword in JavaScript?

In JavaScript, the this keyword refers to the object that owns the current code being executed. The value of this depends on how a function is called:

  1. Global Context: In the global context (outside of any function), this refers to the global object (window in a browser, global in Node.js).console.log(this === window); // true in a browser
  2. Function Context: Inside a function, the value of this depends on how the function is called:
    • Regular Function: In a regular function, this refers to the global object (window in a browser) when the function is called in the global context, or to the object that calls the function when it’s called as a method of an object.function myFunction() { console.log(this); } myFunction(); // Logs the global object (window in a browser) const obj = { method: function() { console.log(this); } }; obj.method(); // Logs the obj object
    • Arrow Function: In an arrow function, this retains the value of the enclosing lexical context (the context in which the arrow function is defined), regardless of how or where it is called.const obj = { method: function() { const innerFunction = () => { console.log(this); }; innerFunction(); } }; obj.method(); // Logs the obj object
  3. Event Handlers: In event handlers, this usually refers to the element that triggered the event.html<button onclick="console.log(this)">Click me</button>
  4. Constructor Functions: In a constructor function (a function invoked with the new keyword), this refers to the newly created object.function Person(name) { this.name = name; console.log(this); } const person = new Person('John'); // Logs the newly created Person object

Understanding the behavior of this is essential for writing object-oriented JavaScript code and handling context correctly in various situations.

10. The conventions of naming a variable in JavaScript?

In JavaScript, naming conventions for variables are not strictly enforced by the language itself, but there are common practices and conventions followed by most developers to write clean, readable, and maintainable code. Here are some widely accepted conventions:

  1. Use Meaningful Names: Choose variable names that accurately describe the data they hold or the purpose they serve. This makes your code more readable and easier to understand.
    // Good const userName = 'John'; // Avoid const x = 'John';
  2. Use CamelCase: Use camelCase for variable names, starting with a lowercase letter and capitalizing each subsequent word.
    const firstName = 'John'; const lastName = 'Doe';
  3. Avoid Single Letter Names: Avoid using single-letter variable names except for simple loop counters (i, j, k) or well-known conventional uses (x, y, z for coordinates).
    // Good const index = 0; // Avoid const i = 0;
  4. Be Consistent: Maintain consistency in your naming conventions throughout your codebase to make it easier for others (or yourself) to understand.
    const fullName = 'John Doe'; const emailAddress = 'john@example.com';
  5. Use Descriptive Names: Use descriptive names that convey the purpose of the variable.
    const numberOfStudents = 10; const totalPrice = calculateTotalPrice();
  6. Prefixes/Suffixes for Specific Types: Optionally, you can use prefixes or suffixes to denote the type of variable (e.g., is, has, count, list, array, map).
    const isLogged = true; const errorOccurred = false; const userList = ['John', 'Jane', 'Alice'];
  7. Constants: Use uppercase letters and underscores for constants to distinguish them from regular variables.const MAX_LENGTH = 100; const PI = 3.14;
  8. Avoid Reserved Keywords: Avoid using reserved keywords (e.g., let, const, function, return, if, else, etc.) as variable names to prevent conflicts and confusion.
    // Avoid let let = 'variable';

By following these naming conventions, you can improve the readability, maintainability, and consistency of your JavaScript code, making it easier for yourself and others to understand and work with.

11. Callback in JavaScript?

In JavaScript, a callback is a function that is passed as an argument to another function and is executed after some operation or task has been completed. Callbacks are commonly used in asynchronous programming to handle tasks like fetching data from a server, processing files, or responding to user interactions.

Here’s how callbacks work:

  1. Passing a Function as an Argument: You define a function and pass it as an argument to another function.
    function fetchData(callback) {
    setTimeout(() => {
    const data = { name: 'John', age: 30 };
    callback(data); }, 1000);
    }
    function processData(data)
    { console.log('Data received:', data); }
    fetchData(processData);
  2. Executing the Callback: Inside the main function (fetchData in this example), you execute the callback function once the main operation (fetching data in this case) is complete.In the example above, fetchData simulates fetching data from a server using setTimeout, and once the data is available, it calls the processData function with the retrieved data as an argument.

Callbacks are essential in handling asynchronous operations in JavaScript, such as AJAX requests, file I/O operations, and event handling. They allow you to specify what should happen once a task is completed without blocking the execution of other code.

However, nested callbacks can lead to callback hell or the pyramid of doom, making code hard to read and maintain. To mitigate this, modern JavaScript provides alternatives like Promises and async/await, which offer cleaner and more readable ways to handle asynchronous code.

12. Debug a JavaScript code?

Debugging JavaScript code involves identifying and fixing errors, unexpected behavior, or issues in your code. Here’s a step-by-step guide on how to debug JavaScript code:

  1. Understand the Problem: Before debugging, make sure you understand the problem you’re trying to solve and have a clear idea of the expected behavior.
  2. Use Browser Developer Tools: Most modern web browsers come with built-in developer tools that include powerful debugging features. You can open the developer tools by pressing F12 or right-clicking on the page and selecting “Inspect” or “Inspect Element.”
  3. Inspect Console Messages: Check for any error messages, warnings, or log statements in the console. These messages can provide valuable information about what went wrong and where the issue occurred.
  4. Set Breakpoints: Place breakpoints in your code to pause execution at specific lines. This allows you to inspect the state of variables, step through code execution, and identify the root cause of the problem.
    • In the Sources tab of your browser’s developer tools, navigate to the JavaScript file containing the code you want to debug.
    • Click on the line number where you want to set a breakpoint to toggle the breakpoint marker.
  5. Step Through Code: Once execution pauses at a breakpoint, use the debugging controls (e.g., step into, step over, step out) to navigate through your code line by line. This helps you understand how the code is executed and identify any logic errors or unexpected behavior.
  6. Inspect Variables: While debugging, inspect the values of variables and expressions to ensure they have the expected values. You can hover over variables to see their current values or use the console to evaluate expressions.
  7. Watch Expressions: You can add expressions to watch during debugging to monitor their values as you step through the code. This can help you track the state of specific variables or conditions.
  8. Use Console Statements: Insert console.log statements strategically throughout your code to log relevant information, such as variable values, function calls, or control flow. These statements can provide additional insights into the code’s behavior and help narrow down the issue.
  9. Isolate the Problem: If debugging a large codebase, try to isolate the problem by gradually commenting out or removing parts of the code until the issue no longer occurs. This can help you identify the specific code causing the problem.
  10. Fix the Issue: Once you’ve identified the cause of the problem, make the necessary changes to fix the issue. Test your code to ensure the problem is resolved and the desired behavior is achieved.

By following these steps and leveraging the debugging tools available in your browser, you can effectively debug JavaScript code and resolve issues efficiently.

13. Difference between Function declaration and Function expression?

Function declaration and function expression are two ways to define functions in JavaScript, and they have some key differences in terms of syntax and behavior.

Function Declaration:

A function declaration is a statement that defines a named function using the function keyword. It consists of the function name, followed by a parameter list (if any), and the function body enclosed in curly braces {}.

function sayHello(name) {
    console.log('Hello, ' + name + '!');
}

Key Characteristics:

  • Hoisted: Function declarations are hoisted to the top of their containing scope during the compilation phase. This means you can call the function before it is declared in the code.
sayHello('John'); // Works fine even though sayHello is called before its declaration

function sayHello(name) {
    console.log('Hello, ' + name + '!');
}
  • Named: Function declarations have a name identifier, which is used to call the function.
sayHello('John'); // Outputs: Hello, John!

function sayHello(name) {
    console.log('Hello, ' + name + '!');
}

Function Expression:

A function expression defines a function as part of an expression, typically by assigning it to a variable. Function expressions can be named or anonymous.

// Named function expression
const sayHello = function greet(name) {
    console.log('Hello, ' + name + '!');
};

// Anonymous function expression
const sayHello = function(name) {
    console.log('Hello, ' + name + '!');
};

Key Characteristics:

  • Not Hoisted: Function expressions are not hoisted like function declarations. They must be defined before they are called.
sayHello('John'); // Error: sayHello is not defined

const sayHello = function(name) {
    console.log('Hello, ' + name + '!');
};
  • May be Named (in named function expressions): Named function expressions provide a name identifier that can be used within the function to refer to itself. This is useful for recursion and function stack traces.
const sayHello = function greet(name) {
    console.log('Hello, ' + name + '!');
};

Summary:

  • Function declarations are hoisted and have a name identifier.
  • Function expressions are not hoisted (except for named function expressions) and can be named or anonymous.
  • Both can be used to define functions, but their behavior regarding hoisting and naming differs.

In general, function declarations are often preferred for their hoisting behavior and named identifiers, while function expressions offer more flexibility, especially for creating functions dynamically or as part of other expressions.

14. What is cookies in JavaScript?

In JavaScript, cookies are small pieces of data stored on the client-side (user’s browser) that are sent back and forth between the client and the server with each HTTP request. Cookies are commonly used to store information about the user or their interactions with the website.

Here are some key points about cookies in JavaScript:

  1. Storage Location: Cookies are stored on the client-side, typically in a text file on the user’s device (e.g., computer, smartphone, tablet). Each cookie is associated with a specific domain and path.
  2. Purpose: Cookies are used for various purposes, including:
    • Session Management: Keeping track of user sessions and maintaining user authentication.
    • Personalization: Storing user preferences or settings.
    • Tracking: Tracking user behavior and activities (e.g., for analytics or advertising).
    • Shopping Carts: Storing items in the user’s shopping cart during an online session.
    • Remembering User Information: Remembering user login credentials or other information for future visits.
  3. Structure: A cookie is represented as a key-value pair, where the key is the name of the cookie and the value is the data associated with it. Cookies may also have additional attributes such as expiration date, domain, and path.
  4. Accessing Cookies: In JavaScript, you can access and manipulate cookies using the document.cookie property. This property allows you to read, write, and delete cookies.
    • Reading Cookies:const cookies = document.cookie; console.log(cookies);
    • Writing Cookies:document.cookie = 'username=John Doe; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/';
    • Deleting Cookies:document.cookie = 'username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
  5. Security Considerations: While cookies are widely used, they also raise privacy and security concerns. Cookies can be manipulated or accessed by malicious actors if not properly secured. Therefore, sensitive information should not be stored in cookies, and measures such as encryption and secure transmission should be used when dealing with sensitive data.

Overall, cookies are a fundamental mechanism for maintaining state and user interactions in web applications, but they should be used responsibly and in accordance with privacy regulations and best practices.

15. How do create cookies in JavaScript?

In JavaScript, you can create cookies by setting the document.cookie property with a string containing the cookie’s key-value pair and any optional attributes. Here’s how you can create cookies using JavaScript:

// Create a cookie named "username" with the value "John Doe"
document.cookie = "username=John Doe";

// Create a cookie with additional attributes (expires, path, domain)
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/";

// Create a cookie with multiple key-value pairs
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/; email=john@example.com";

When setting cookies, you provide a string with the following format:

"key=value; [expires=date;] [path=path;] [domain=domain;] [secure;] [samesite=strict|lax|none;]"

Here’s a breakdown of each part:

  • key=value: The name-value pair of the cookie.
  • expires=date: (Optional) Specifies the expiration date and time of the cookie. If not specified, the cookie is treated as a session cookie and is deleted when the browser is closed.
  • path=path: (Optional) Specifies the path for which the cookie is valid. By default, the cookie is valid for the current path.
  • domain=domain: (Optional) Specifies the domain for which the cookie is valid. By default, the cookie is valid for the current domain.
  • secure: (Optional) Specifies that the cookie should only be sent over secure HTTPS connections.
  • samesite=strict|lax|none: (Optional) Specifies the SameSite attribute of the cookie, which controls when the cookie is sent in cross-site requests.

After setting a cookie, it will be included in subsequent HTTP requests to the same domain and path, allowing you to retrieve and use the cookie’s value on the server-side or client-side as needed.

16. How to delete cookies in JavaScript ?

To delete cookies in JavaScript, you can set the cookie’s expiration date to a past date, which effectively removes the cookie from the browser’s cookie storage. Here’s how you can delete a cookie using JavaScript:

// Set the expiration date of the cookie to a past date
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";

In this example, we’re setting the expiration date of the “username” cookie to January 1, 1970, which is a date in the past. When the browser sees that the expiration date of a cookie has passed, it automatically removes the cookie from its storage.

You should also specify the same path and domain that you used when setting the cookie to ensure that you’re deleting the correct cookie. If the path and domain are not specified, the browser will only delete cookies with the same path and domain as the current page.

If the cookie you want to delete has additional attributes (e.g., domain, path), make sure to include those attributes when setting the expiration date to ensure that the browser correctly identifies the cookie to delete.

Here’s a more general function to delete a cookie by name:

function deleteCookie(name) {
    document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
}

You can call this function with the name of the cookie you want to delete:

deleteCookie('username');

This function sets the expiration date of the specified cookie to a past date, effectively deleting the cookie from the browser’s storage.

17. Difference between let, var and const?

In JavaScript, let, var, and const are used to declare variables, but they have some differences in terms of scope, hoisting, and mutability. Here’s a comparison of each:

  1. var:
    • Scope: Variables declared with var have function scope. They are visible throughout the function in which they are defined, regardless of block scope.
    • Hoisting: var variables are hoisted to the top of their containing function or global scope during the compilation phase. This means you can access the variable before it’s declared in the code.
    • Reassignment: You can reassign and update the value of a var variable.
    var x = 10; var x = 20; // Reassignment x = 30; // Update
  2. let:
    • Scope: Variables declared with let have block scope. They are only visible within the block (i.e., within curly braces {}) where they are defined.
    • Hoisting: let variables are hoisted to the top of their containing block, but their initialization is not hoisted. This means you cannot access the variable before it’s declared in the code.
    • Reassignment: You can reassign and update the value of a let variable.
    let y = 10; y = 20; // Reassignment
  3. const:
    • Scope: Variables declared with const also have block scope, similar to let.
    • Hoisting: Like let, const variables are hoisted to the top of their containing block, but their initialization is not hoisted. You cannot access the variable before it’s declared.
    • Reassignment: Variables declared with const are constant; their value cannot be reassigned once initialized. However, if the variable is an object or array, its properties or elements can be mutated.
    const z = 10; z = 20; // Error: Assignment to constant variable const obj = { name: 'John' }; obj.name = 'Jane'; // Mutation allowed

Summary:

  • Use const for variables that should not be reassigned.
  • Use let for variables that may be reassigned.
  • Avoid using var due to its function-scoped nature and hoisting behavior, unless you specifically need its behavior.
  • Always prefer const when declaring variables that won’t be reassigned, as it makes your code more predictable and safer. Use let for variables that need to be reassigned, and use var only if you specifically need its function scope or hoisting behavior, which is rare in modern JavaScript development.

18. What is Closures in JavaScript?

Closures are an important concept in JavaScript that allows functions to retain access to variables from their lexical scope even after the outer function has finished executing. In simpler terms, a closure is the combination of a function and the lexical environment within which that function was declared.

Here’s an example to illustrate how closures work:

function outerFunction() {
    const outerVariable = 'I am from the outer function';
    
    function innerFunction() {
        console.log(outerVariable); // Accesses outerVariable from the outer function's scope
    }

    return innerFunction;
}

const innerFunc = outerFunction();
innerFunc(); // Outputs: I am from the outer function

In this example:

  • outerFunction defines a variable outerVariable and declares an inner function innerFunction.
  • innerFunction has access to outerVariable due to closure, even though outerFunction has finished executing.
  • When innerFunction is returned and assigned to innerFunc, it retains access to outerVariable and can still log its value.

Closures are commonly used in JavaScript for:

  • Encapsulating data: By enclosing variables within a function’s scope, you can prevent them from being accessed or modified from outside the function.
  • Maintaining state: Closures can be used to create private variables or to retain the state of a function between invocations.

Here’s another example demonstrating how closures can be used to create private variables:

function counter() {
    let count = 0;

    return function() {
        count++;
        console.log(count);
    };
}

const increment = counter();
increment(); // Outputs: 1
increment(); // Outputs: 2
increment(); // Outputs: 3

In this example, the counter function returns an inner function that increments and logs a count variable. The count variable is private to the counter function and can only be accessed and modified through the closure returned by counter.

Understanding closures is essential for writing clean, modular, and efficient JavaScript code, especially when dealing with asynchronous operations, callbacks, and functional programming paradigms.

19. What is arrow functions in JavaScript?

Arrow functions, introduced in ECMAScript 2015 (ES6), provide a concise syntax for writing functions in JavaScript. They offer a more compact and expressive way to define functions compared to traditional function expressions. Here’s an overview of arrow functions:

  1. Syntax:
    • Arrow functions are defined using the arrow (=>) syntax.
    • They can have either a concise body (implicit return) or a block body (explicit return).
    // Concise body const add = (a, b) => a + b; // Block body const subtract = (a, b) => { return a - b; };
  2. Parameters:
    • Arrow functions support zero or more parameters enclosed in parentheses (()).
    • If there’s only one parameter, you can omit the parentheses.
    const greet = name => console.log(`Hello, ${name}!`); greet('John'); // Outputs: Hello, John!
  3. Return Value:
    • Arrow functions with a concise body automatically return the expression’s value.
    • If using a block body, you need to explicitly specify the return value using the return keyword.
  4. Lexical this Binding:
    • Arrow functions do not have their own this context. Instead, they inherit the this value from the surrounding lexical scope.
    const person = { name: 'John', greet: function() { // 'this' refers to the 'person' object setTimeout(() => { console.log(`Hello, ${this.name}!`); }, 1000); } }; person.greet(); // Outputs: Hello, John!
  5. No arguments object:
    • Arrow functions do not have their own arguments object. Instead, they inherit the arguments from the surrounding scope.
    function sum() { const add = () => { console.log(arguments); }; add(); } sum(1, 2, 3); // Outputs: [1, 2, 3]

Arrow functions are widely used in modern JavaScript development for their concise syntax, lexical this binding, and compatibility with functional programming paradigms. However, it’s important to understand their behavior, especially regarding this binding, to avoid unexpected results.

20. Imports and Exports in JavaScript?

Imports and exports are features introduced in ECMAScript 2015 (ES6) for modularizing JavaScript code, allowing you to split your code into multiple files and organize it more effectively. Here’s an overview of imports and exports in JavaScript:

Exporting from a Module:

You can export functions, variables, classes, or objects from a module using the export keyword.

Named Exports:

// Named export
export const sum = (a, b) => a + b;

// Named export
export function multiply(a, b) {
    return a * b;
}

// Named export
export const PI = 3.14;

// Named export
export const person = {
    name: 'John',
    age: 30
};

Default Export:

// Default export
export default function sayHello(name) {
    console.log(`Hello, ${name}!`);
}

Importing in Another Module:

You can import named exports and default exports from another module using the import keyword.

Named Imports:

// Named imports
import { sum, multiply, PI, person } from './math';

console.log(sum(2, 3)); // Outputs: 5
console.log(multiply(2, 3)); // Outputs: 6
console.log(PI); // Outputs: 3.14
console.log(person.name); // Outputs: John

Default Import:

// Default import
import sayHello from './greetings';

sayHello('John'); // Outputs: Hello, John!

Renaming Imports:

You can rename named imports during import to avoid naming conflicts or provide more descriptive names.

import { sum as addition } from './math';

console.log(addition(2, 3)); // Outputs: 5

Importing Everything from a Module:

You can import all named exports from a module using the * as syntax.

import * as math from './math';

console.log(math.sum(2, 3)); // Outputs: 5
console.log(math.multiply(2, 3)); // Outputs: 6
console.log(math.PI); // Outputs: 3.14
console.log(math.person.name); // Outputs: John

Imports and exports enable you to create modular and reusable JavaScript code, facilitating better code organization, maintainability, and collaboration in larger projects. They also help in reducing global namespace pollution and managing dependencies effectively.

21. Difference between Document and Window in JavaScript?

In JavaScript, Document and Window are two different objects that represent different aspects of the web page environment.

Window:

  • The Window object represents the browser window or tab that contains the web page.
  • It is the top-level object in the browser’s JavaScript object model (DOM).
  • It provides properties and methods for controlling the browser window, such as navigating to URLs (window.location), opening new windows or tabs (window.open()), and setting timeouts or intervals (window.setTimeout(), window.setInterval()).
  • The Window object also serves as the global object for JavaScript code running within the browser environment. Global variables and functions are defined as properties and methods of the Window object.
  • Examples of properties/methods on the Window object: window.innerWidth, window.innerHeight, window.alert(), window.console.log().

Document:

  • The Document object represents the web page itself, including its content, structure, and elements.
  • It is a child object of the Window object and is accessible through the window.document property.
  • The Document object provides methods and properties for interacting with the HTML document, such as selecting elements (document.getElementById(), document.querySelector()), modifying element content (element.innerHTML, element.textContent), and handling events (element.addEventListener()).
  • The Document object also provides access to various collections of elements within the document, such as the document.getElementsByTagName(), document.getElementsByClassName(), and document.querySelectorAll() methods.
  • Examples of properties/methods on the Document object: document.title, document.body, document.getElementById(), document.querySelector().

Summary:

  • Window represents the browser window/tab and provides methods and properties for controlling the browser environment.
  • Document represents the web page and provides methods and properties for interacting with the HTML document structure and content.

While Window is the top-level object in the browser environment, Document is a child object of Window and represents the content of the web page within the window/tab.

22. JavaScript frameworks and their uses?

JavaScript frameworks are libraries of pre-written JavaScript code that provide developers with a set of tools and utilities to simplify and accelerate the development of web applications. They typically offer solutions for common tasks such as DOM manipulation, data binding, routing, state management, and more. Here are some popular JavaScript frameworks and their primary uses:

React:

Use: Building user interfaces (UIs) for web applications.

Features:

  • Component-based architecture for building reusable UI elements.
  • Virtual DOM for efficient rendering and performance optimization.
  • JSX syntax for embedding HTML-like code within JavaScript.
  • One-way data flow with uni-directional data binding.
  • Example: Facebook, Instagram, Airbnb.

Angular:

Use: Building large-scale, single-page applications (SPAs).

Features:

  • Full-featured framework with built-in modules for routing, HTTP requests, forms, etc.
  • Two-way data binding for automatic synchronization between model and view.
  • Dependency injection for managing components and services.
  • TypeScript support for static typing and enhanced tooling.
  • Example: Google, Microsoft, PayPal.

Vue.js:

Use: Building interactive and reactive web interfaces.

Features:

  • Progressive framework for building UIs incrementally.
  • Virtual DOM with reactive data binding for efficient rendering.
  • Component-based architecture similar to React.
  • Vue CLI for scaffolding and managing Vue projects.
  • Example: Alibaba, Xiaomi, Nintendo.

Ember.js:

Use: Building ambitious web applications with complex UIs.

Features:

  • Opinionated framework with conventions over configuration.
  • Ember CLI for project scaffolding, build tooling, and development workflow.
  • Ember Data for managing application data and interacting with backend APIs.
  • Handlebars templating engine for building dynamic HTML.
  • Example: LinkedIn, Discourse, Square.

Svelte:

Use: Building highly efficient and lightweight web applications.

Features:

  • Compiler-based framework that generates highly optimized JavaScript code.
  • No virtual DOM; updates DOM directly at build time.
  • Reactive data bindings and component-based architecture.
  • Easy integration with existing JavaScript libraries and frameworks.
  • Example: New York Times, GoDaddy, Square.

Backbone.js:

Use: Providing structure to web applications by adding models, collections, and views.

Features:

  • Lightweight library for adding structure to client-side code.
  • Provides models with key-value binding and custom events.
  • Collections for managing lists of models.
  • Views for rendering UI templates and handling user interactions.
  • Example: Airbnb, Hulu, SoundCloud.

23. Difference between Undefined and Undeclared in JavaScript?

In JavaScript, “undefined” and “undeclared” are two distinct concepts related to variables.

Undefined:

  • “Undefined” is a primitive data type in JavaScript that represents the absence of a value or the uninitialized state of a variable.
  • When you declare a variable but do not assign a value to it, or if you access a property that does not exist on an object, the value of the variable or property will be “undefined”.
  • Example:let x; console.log(x); // Outputs: undefined let obj = {}; console.log(obj.property); // Outputs: undefined

Undeclared:

  • “Undeclared” refers to a variable that has not been declared using the var, let, or const keywords in any scope.
  • If you try to reference an undeclared variable, JavaScript will throw a ReferenceError.
  • Example:console.log(y); // Throws ReferenceError: y is not defined

Summary:

  • “Undefined” is a value that represents the absence of a value or the uninitialized state of a variable.
  • “Undeclared” refers to a variable that has not been declared using the var, let, or const keywords in any scope.
  • Accessing an undeclared variable results in a ReferenceError, while accessing an uninitialized variable or a non-existent property results in “undefined”.

24. Difference between Undefined and Null in JavaScript?

In JavaScript, “undefined” and “null” are both primitive data types that represent absence of value, but they have different meanings and use cases:

Undefined:

  • undefined is a primitive data type that represents the absence of a value.
  • It typically occurs when a variable has been declared but has not been assigned a value.
  • It can also occur when trying to access a property of an object that does not exist.
  • Example:let x; console.log(x); // Outputs: undefined let obj = {}; console.log(obj.property); // Outputs: undefined

Null:

  • null is a primitive data type that represents an intentional absence of value or a deliberate assignment to indicate no value.
  • It is often used to explicitly signify that a variable or object property has no value or has been intentionally set to nothing.
  • Example:let y = null; console.log(y); // Outputs: null

Differences:

  1. Assignment: undefined typically occurs when a variable has not been assigned any value, whereas null is used when you want to explicitly indicate that a variable has no value.
  2. Type: undefined is a type itself (along with NaN, Infinity, etc.), while null is a value of the null type.
  3. Automatic vs. Explicit: undefined can occur automatically due to variables being declared but not initialized or properties being accessed on non-existent objects. null, on the other hand, is explicitly assigned when you want to indicate a deliberate absence of value.
  4. Usage: undefined is often encountered in scenarios where a value has not been provided or where a value is expected but not found. null is typically used when you need to assign a variable or object property to signify a lack of value or as a placeholder for an intentional absence of data.

In summary, while both undefined and null represent absence of value in JavaScript, they are used in different contexts and for different purposes. undefined is often encountered automatically in code, while null is explicitly assigned when you want to signify a deliberate absence of value.

25. Difference between Session storage and Local storage?

Session Storage and Local Storage are both mechanisms available in modern web browsers for storing key-value pairs locally within the user’s browser. However, they have some differences in terms of scope, persistence, and usage:

Session Storage:

  • Scope: Session Storage is specific to the current browser tab or window. Each tab or window has its own isolated session storage, and data stored in session storage is accessible only within that tab or window.
  • Persistence: Data stored in session storage is temporary and persists only for the duration of the page session. Once the browser tab or window is closed, the data is cleared from session storage.
  • Usage: Session storage is commonly used to store temporary data that needs to be available only during the current browsing session. It’s often used for storing session-specific information such as user authentication tokens, temporary preferences, or data needed for multi-step processes within a single session.

Local Storage:

  • Scope: Local Storage is global to the entire origin (i.e., protocol, domain, and port combination). Data stored in local storage is shared across all tabs and windows from the same origin.
  • Persistence: Data stored in local storage persists even after the browser is closed and reopened. It remains stored indefinitely until explicitly cleared by the user or the application.
  • Usage: Local storage is commonly used for storing long-term data such as user preferences, application settings, cached data, or any data that needs to be retained across multiple sessions or browser restarts.

Summary:

  • Scope: Session Storage is isolated to the current tab or window, while Local Storage is shared across all tabs and windows from the same origin.
  • Persistence: Data in Session Storage is temporary and cleared when the tab or window is closed, while data in Local Storage persists indefinitely until cleared manually.
  • Usage: Session Storage is suitable for temporary session-specific data, while Local Storage is suitable for long-term data storage needs.

Both Session Storage and Local Storage provide simple and convenient APIs for storing and retrieving data in web applications, allowing developers to enhance user experiences by persisting data locally within the browser. The choice between them depends on the specific requirements of the application and the desired lifespan of the stored data.

26. Difference between Call and Apply in JavaScript ?

In JavaScript, both call() and apply() are methods available on function objects that allow you to invoke a function and explicitly specify the value of this and pass arguments to the function. While they achieve similar goals, they differ in how they accept arguments.

call() Method:

  • The call() method is used to invoke a function with a specified this value and arguments provided individually.
  • The first argument to call() is the value of this within the function being called.
  • Subsequent arguments are passed to the function as individual arguments.
  • Syntax: function.call(thisArg, arg1, arg2, ...)
  • Example:const person = { name: 'John', greet: function(message) { console.log(`${message}, ${this.name}!`); } }; const anotherPerson = { name: 'Jane' }; person.greet.call(anotherPerson, 'Hello'); // Outputs: Hello, Jane!

apply() Method:

  • The apply() method is similar to call(), but it accepts arguments as an array or array-like object.
  • The first argument to apply() is the value of this within the function being called.
  • The second argument is an array-like object containing the arguments to be passed to the function.
  • Syntax: function.apply(thisArg, [arg1, arg2, ...])
  • Example:const person = { name: 'John', greet: function(message) { console.log(`${message}, ${this.name}!`); } }; const anotherPerson = { name: 'Jane' }; person.greet.apply(anotherPerson, ['Hello']); // Outputs: Hello, Jane!

Differences:

  • The main difference between call() and apply() is how they accept arguments. call() accepts arguments individually, while apply() accepts arguments as an array or array-like object.
  • You may choose call() over apply() when you know the exact number of arguments you want to pass, while apply() can be useful when dealing with variable numbers of arguments or when the arguments are already in an array-like structure.
  • In terms of performance, call() generally performs better than apply() because it doesn’t have to construct an array from arguments.

In summary, call() and apply() are both used to invoke functions with a specific value of this, but they differ in how they accept arguments. Use call() when you have a fixed number of arguments to pass, and use apply() when dealing with variable numbers of arguments or when arguments are already in an array-like structure.

27. Scopes of a variable in JavaScript?

In JavaScript, the scope of a variable refers to the region of code where the variable is accessible. The scope of a variable is determined by where it is declared, and variables can have different scopes depending on where they are declared. There are three main types of scope in JavaScript:

  1. Global Scope:
    • Variables declared outside of any function or block have global scope.
    • Global variables are accessible from anywhere in the code, including inside functions and blocks.
    • They are attached to the window object in browsers.
    • Example:// Global variable let globalVar = 'I am global'; function myFunction() { console.log(globalVar); // Accessible } myFunction(); // Outputs: I am global
  2. Function Scope:
    • Variables declared inside a function have function scope.
    • Function-scoped variables are accessible only within the function in which they are declared.
    • They are not accessible from outside the function.
    • Example:function myFunction() { let localVar = 'I am local'; console.log(localVar); // Accessible } myFunction(); // Outputs: I am local console.log(localVar); // ReferenceError: localVar is not defined
  3. Block Scope (ES6+):
    • Variables declared with let and const inside a block (e.g., within {} in if statements, loops, or functions) have block scope.
    • Block-scoped variables are accessible only within the block in which they are declared.
    • They are not accessible from outside the block.
    • Example:if (true) { let blockVar = 'I am block-scoped'; console.log(blockVar); // Accessible } console.log(blockVar); // ReferenceError: blockVar is not defined

In addition to the above types of scope, JavaScript also has lexical scope, which means that inner functions have access to variables declared in their outer (enclosing) scope. This allows for closures, where inner functions “remember” the environment in which they were created.

Understanding variable scope is crucial for writing clean and maintainable JavaScript code, as it helps prevent naming conflicts, manage variable lifetimes, and control access to data within different parts of your program.

28. Difference between “ == “ and “ === “ operators

In JavaScript, both the “==” (equality) and “===” (strict equality) operators are used to compare values, but they behave differently based on their comparison rules.

“==” (Equality Operator):

  • The “==” operator performs type coercion, which means it converts the operands to the same type before making the comparison.
  • If the operands are of different types, JavaScript attempts to convert them to a common type before comparing.
  • After conversion, it compares the values of the operands.
  • Example:console.log(1 == '1'); // Outputs: true (String '1' is converted to Number 1) console.log(0 == false); // Outputs: true (Boolean false is converted to Number 0)

“===” (Strict Equality Operator):

  • The “===” operator checks for strict equality without type coercion.
  • It compares both the values and the types of the operands. The values must be of the same type and have the same value for the comparison to return true.
  • If the types of the operands are different, the comparison returns false without attempting any type conversion.
  • Example:console.log(1 === '1'); // Outputs: false (Number 1 is not equal to String '1') console.log(0 === false); // Outputs: false (Number 0 is not equal to Boolean false)

Key Differences:

  • “==” performs type coercion and compares values after conversion, while “===” does not perform type coercion and compares both values and types.
  • “==” may lead to unexpected results due to implicit type conversion, especially when comparing values of different types.
  • “===” is generally considered safer and more predictable for equality comparisons, as it avoids unintended type coercion and ensures strict type and value equality.

In summary, use “==” when you want to allow type coercion and “===” when you want to ensure strict type and value equality without type conversion. In most cases, it’s recommended to use “===” for equality comparisons to avoid unexpected behavior caused by implicit type coercion.

29. Implicit Type Coercion in JavaScript

Implicit type coercion in JavaScript refers to the automatic conversion of values from one data type to another by the JavaScript engine during certain operations or comparisons. This conversion happens implicitly, without the need for explicit type conversion functions like parseInt() or toString(). Implicit type coercion can occur in various contexts, such as arithmetic operations, comparison operators, and logical operators.

Here are some common scenarios where implicit type coercion occurs:

  1. Arithmetic Operations:console.log(5 + '5'); // Outputs: "55" (Number 5 is coerced to String '5' before concatenation) console.log('10' - 5); // Outputs: 5 (String '10' is coerced to Number 10 before subtraction)
  2. Comparison Operators:console.log(10 == '10'); // Outputs: true (Number 10 is coerced to String '10' for comparison) console.log(0 == false); // Outputs: true (Boolean false is coerced to Number 0 for comparison)
  3. Logical Operators:console.log(0 || 'Hello'); // Outputs: "Hello" (Falsy value 0 is coerced to Boolean false, 'Hello' is truthy) console.log(null && 'World'); // Outputs: null (Truthy value null is coerced to Boolean true, short-circuiting)
  4. Conditional (Ternary) Operator:const x = 10; const result = x > 5 ? 'Greater than 5' : 'Less than or equal to 5'; // No coercion here, just an example

While implicit type coercion can be convenient and helpful in certain situations, it can also lead to unexpected behavior and bugs if not understood properly. It’s important for developers to be aware of implicit type coercion and understand how it affects their code. In many cases, it’s recommended to use strict equality (===) and explicit type conversion functions to ensure more predictable behavior and avoid unintended consequences caused by implicit type coercion.

30. NaN property in JavaScript

In JavaScript, NaN stands for “Not-a-Number.” It is a special value that represents the result of an operation that cannot produce a meaningful numeric result. The NaN value is returned when a mathematical operation fails or when the result cannot be represented as a valid number.

NaN is a property of the global object (window in browsers) and is of the data type “Number.”

Here are some common scenarios where NaN is encountered:

  1. Failed Mathematical Operations:console.log(Math.sqrt(-1)); // Outputs: NaN (Square root of a negative number is not a real number) console.log(0 / 0); // Outputs: NaN (Division by zero) console.log(NaN + 5); // Outputs: NaN (Adding any value to NaN results in NaN)
  2. Conversion Failures:console.log(parseInt('Hello')); // Outputs: NaN (Parsing a non-numeric string) console.log(parseFloat('3.14.5')); // Outputs: NaN (Invalid floating point number)
  3. Indicating Invalid Result:function calculateSquareRoot(num) { if (num < 0) { return NaN; // Indicating that the result is invalid for negative numbers } return Math.sqrt(num); } console.log(calculateSquareRoot(-9)); // Outputs: NaN
  4. Comparison with NaN:console.log(NaN === NaN); // Outputs: false (NaN is not equal to itself) console.log(isNaN(NaN)); // Outputs: true (Use isNaN() function to check if a value is NaN)

Since NaN is not equal to any other value, including itself, you should always use the isNaN() function to check whether a value is NaN.

console.log(isNaN(NaN)); // Outputs: true
console.log(isNaN(5)); // Outputs: false
console.log(isNaN('hello')); // Outputs: true (Attempting to convert a non-numeric string results in NaN)

It’s important to handle NaN values appropriately in your code to avoid unexpected behavior or errors. You can check for NaN using isNaN() or by comparing with NaN directly, depending on the context.

31. Passed by value and passed by reference in JavaScript

In JavaScript, when you pass a variable to a function, the behavior of passing can be described as either “passed by value” or “passed by reference,” depending on the data type of the variable being passed.

Passed by Value:

  • When you pass a primitive data type (such as numbers, strings, or booleans) to a function, a copy of the value is passed.
  • Changes made to the parameter inside the function do not affect the original value outside the function.
  • Example:function modifyValue(x) { x = x * 2; // Changes made to x inside the function do not affect the original value of x console.log('Inside function:', x); // Outputs: 20 } let num = 10; modifyValue(num); console.log('Outside function:', num); // Outputs: 10

Passed by Reference:

  • When you pass a non-primitive data type (such as objects or arrays) to a function, a reference to the original object is passed.
  • Any changes made to the parameter inside the function affect the original object outside the function, as they both point to the same memory location.
  • Example:function modifyArray(arr) { arr.push(4); // Changes made to arr inside the function affect the original array console.log('Inside function:', arr); // Outputs: [1, 2, 3, 4] } let array = [1, 2, 3]; modifyArray(array); console.log('Outside function:', array); // Outputs: [1, 2, 3, 4]

Summary:

  • Primitive data types are passed by value in JavaScript. Changes made to the parameter inside the function do not affect the original value outside the function.
  • Non-primitive data types (objects, arrays, etc.) are passed by reference. Changes made to the parameter inside the function affect the original object/array outside the function.

Understanding the distinction between passing by value and passing by reference is important for writing predictable and maintainable code in JavaScript, especially when working with complex data structures.

32. What is Invoked Function in JavaScript?

An invoked function in JavaScript refers to a function that has been called or executed. When you invoke a function, you are telling JavaScript to execute the code defined within that function. There are several ways to invoke a function in JavaScript:

  1. Function Invocation: You can invoke a function by simply writing its name followed by parentheses () containing any arguments (if applicable). This is the most common way to invoke functions.function greet() { console.log('Hello, world!'); } greet(); // Invoking the greet function
  2. Method Invocation: If a function is a property of an object, you can invoke it as a method of that object using dot notation.const person = { name: 'John', greet: function() { console.log('Hello, ' + this.name + '!'); } }; person.greet(); // Invoking the greet method of the person object
  3. Constructor Invocation: You can invoke a function as a constructor using the new keyword. This creates a new instance of an object based on the constructor function.function Person(name) { this.name = name; } const john = new Person('John'); // Invoking Person as a constructor
  4. Indirect Invocation using Call and Apply: You can invoke a function indirectly using the call() or apply() methods, which allow you to specify the value of this and pass arguments explicitly.function greet(greeting) { console.log(greeting + ', ' + this.name + '!'); } const person = { name: 'John' }; greet.call(person, 'Hello'); // Indirect invocation using call greet.apply(person, ['Hello']); // Indirect invocation using apply
  5. Immediately Invoked Function Expression (IIFE): An IIFE is a function that is declared and invoked immediately after its definition. This pattern is often used to create a private scope and avoid polluting the global namespace.(function() { console.log('I am an immediately invoked function expression (IIFE)'); })();

These are some of the common ways to invoke functions in JavaScript. Understanding how to invoke functions is fundamental to writing effective JavaScript code, as functions are essential building blocks for organizing and encapsulating logic in JavaScript applications.

33. Difference between exec () and test () methods in JavaScript

In JavaScript, both the exec() and test() methods are used in combination with regular expressions to search for patterns within strings. However, they have different purposes and behaviors:

1. exec() Method:

  • The exec() method is a method of the RegExp object. It searches a string for a match against a regular expression and returns an array containing information about the match.
  • If a match is found, exec() returns an array containing the matched text as the first element, followed by any captured groups (if present). If no match is found, it returns null.
  • When the regular expression has the global flag (/g) set, exec() can be called multiple times to find successive matches within the same string. It remembers where it left off in the string and continues the search from there.
  • Example:const str = 'Hello, World!'; const regex = /o/g; let match; while ((match = regex.exec(str)) !== null) { console.log(`Found '${match[0]}' at index ${match.index}`); }

2. test() Method:

  • The test() method is a method of the RegExp object. It tests whether a string matches a regular expression pattern and returns true or false based on the result.
  • Unlike exec(), test() returns a boolean value indicating whether the pattern is found in the string. It does not return information about the specific match.
  • test() is commonly used in conditional statements or as a quick way to check for the presence of a pattern without extracting detailed match information.
  • Example:const str = 'Hello, World!'; const regex = /o/; console.log(regex.test(str)); // Outputs: true

Key Differences:

  • exec() returns an array containing information about the match (or null if no match is found), while test() returns a boolean value indicating whether a match is found.
  • exec() is used when you need to extract detailed information about the match, such as the matched text and captured groups. It’s useful when you need more than just a yes/no answer.
  • test() is used when you only need to check whether a match exists and don’t need detailed match information. It’s simpler and more straightforward for basic pattern matching.

In summary, exec() is used for extracting match details, while test() is used for simple pattern matching to determine if a pattern exists in a string. Both methods are useful in different scenarios, depending on the specific requirements of your application.

34. What is currying in JavaScript?

Currying is a functional programming technique in JavaScript where a function with multiple arguments is transformed into a sequence of nested functions, each taking a single argument. The curried function returns a new function with one less argument until it reaches the final function, which executes and returns the result.

Here’s an example of currying in JavaScript:

// Non-curried function
function add(x, y) {
    return x + y;
}

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

// Curried version of add function
function curriedAdd(x) {
    return function(y) {
        return x + y;
    };
}

const addTwo = curriedAdd(2); // Returns a function that adds 2 to its argument
console.log(addTwo(3)); // Outputs: 5

In this example:

  • The add function takes two arguments x and y and returns their sum.
  • The curriedAdd function takes one argument x and returns a new function that takes another argument y and adds x and y.
  • By partially applying curriedAdd, we create a new function addTwo that adds 2 to its argument. We can then call addTwo with the second argument to get the final result.

Currying can be achieved manually as shown above, or using utility libraries like Lodash or Ramda, which provide built-in functions for currying.

Currying has several benefits:

  1. Partial Application: Curried functions allow partial application, where you can fix some arguments upfront and defer the application of the remaining arguments until later.
  2. Function Composition: Curried functions can be easily composed together to create new functions by chaining multiple function calls.
  3. Code Reusability: Currying promotes code reusability by allowing the creation of specialized functions from more general ones.
  4. Improved Readability: Curried functions can lead to clearer and more readable code, especially in functional programming paradigms.

However, it’s worth noting that currying may not always be the most appropriate solution for every situation, and it’s important to consider factors like performance and readability when deciding whether to use currying in your code.

35. Use of a constructor function in JavaScript

Constructor functions in JavaScript are used to create objects with specific properties and behaviors. They serve as blueprints for creating multiple instances of objects that share similar characteristics. Here’s how constructor functions are typically used:

  1. Defining a Constructor Function: You define a constructor function using the function keyword followed by the name of the function (conventionally capitalized to distinguish it from regular functions).function Person(name, age) { this.name = name; this.age = age; }
  2. Creating Instances: You create instances (objects) of the constructor function using the new keyword followed by the name of the constructor function and any arguments required for initialization.const person1 = new Person('John', 30); const person2 = new Person('Jane', 25);
  3. Initialization: Inside the constructor function, you typically assign values to properties using the this keyword, which refers to the current instance being created.
  4. Properties and Methods: Constructor functions can define properties and methods that are shared by all instances of the object. These properties and methods are attached to the prototype property of the constructor function.Person.prototype.greet = function() { console.log('Hello, my name is ' + this.name); };
  5. Accessing Properties and Methods: You can access properties and methods of an instance using dot notation.console.log(person1.name); // Outputs: 'John' person2.greet(); // Outputs: 'Hello, my name is Jane'

Constructor functions are commonly used in JavaScript to create objects that represent entities in your application, such as users, products, or any other type of data. They provide a convenient way to organize and create objects with consistent properties and behaviors. Additionally, constructor functions can be extended using inheritance to create more complex object hierarchies. However, with the introduction of class syntax in ECMAScript 2015 (ES6), the use of constructor functions for defining classes has become less common, as classes provide a more structured and intuitive syntax for defining object blueprints.

36. How to create virtual DOM in JavaScript ?

Creating a virtual DOM in JavaScript involves creating a lightweight, in-memory representation of the actual DOM (Document Object Model) structure. This virtual representation allows developers to perform efficient updates and manipulations before syncing the changes with the real DOM. Here’s a simplified explanation of how to create a virtual DOM in JavaScript:

Define a Data Structure: Start by defining a data structure that represents the nodes of the virtual DOM. Each node should contain information about its type (e.g., element, text), attributes, children, and other relevant properties.

Create Functions for Creating Nodes: Write functions that create virtual DOM nodes based on the defined data structure. These functions should accept parameters such as element type, attributes, and children, and return a JavaScript object representing the node.

Construct the Virtual DOM Tree: Use the functions for creating nodes to construct the virtual DOM tree by creating nested objects that represent the hierarchy of DOM elements. This virtual tree mirrors the structure of the actual DOM but exists only in memory.

Perform Operations on the Virtual DOM: Once the virtual DOM tree is constructed, you can perform various operations on it, such as adding, removing, or updating nodes. These operations can be performed efficiently because the virtual DOM is lightweight and exists entirely in memory.

Diffing and Reconciliation: After performing operations on the virtual DOM, you can compare it with the previous version (if any) to determine the differences (diffing). This process involves comparing nodes and their attributes to identify changes. Once differences are identified, you can apply them to the real DOM (reconciliation) to update the user interface.

Sync Changes with the Real DOM: Finally, sync the changes from the virtual DOM to the real DOM by applying the identified differences. This step involves creating, updating, or removing actual DOM nodes based on the changes identified during the diffing process.

function createElement(type, props, …children) {
return {
type,
props: props || {},
children
};
}
function renderElement(virtualNode) {
if (typeof virtualNode === ‘string’) {
return document.createTextNode(virtualNode);
}
const element = document.createElement(virtualNode.type);
for (const [prop, value] of Object.entries(virtualNode.props)) {
element[prop] = value;
}
for (const child of virtualNode.children) {
element.appendChild(renderElement(child));
}
return element;
}
const virtualDOM = createElement(‘div’, {
id: ‘container’
},
createElement(‘h1’, {
className: ‘title’
}, ‘Hello, World!’),
createElement(‘p’, null, ‘This is a paragraph.’)
);
const container = document.getElementById(‘app’);
container.appendChild(renderElement(virtualDOM));

37. What is critical rendering path?

The critical rendering path refers to the sequence of steps browsers take to render web pages and display them on the user’s screen. It encompasses everything from fetching resources (HTML, CSS, JavaScript, images, etc.) to processing and rendering the content. Optimizing the critical rendering path is crucial for improving page load times and enhancing user experience. Here’s a high-level overview of the critical rendering path:

  1. HTML Parsing and DOM Construction:
  • The browser starts by fetching the HTML document from the server.
  • As the HTML document is downloaded, the browser parses it and constructs the Document Object Model (DOM), representing the structure of the web page.
  1. CSS Parsing and Style Calculations:
  • While parsing the HTML document, the browser identifies linked and inline CSS resources and begins fetching them.
  • Once CSS resources are downloaded, the browser parses and constructs the CSS Object Model (CSSOM) to represent the styles associated with the DOM elements.
  • The browser then combines the DOM and CSSOM to create the render tree, a representation of the elements on the page that need to be displayed.
  1. Layout (Reflow):
  • The browser calculates the layout of the render tree, determining the size, position, and visibility of each element on the page.
  • This process is known as reflow or layout.
  1. Painting:
  • Finally, the browser paints the pixels on the screen based on the calculated layout and styles.
  • This involves rendering text, applying colors and gradients, rendering images, and drawing borders and shadows.

Optimizing the critical rendering path involves minimizing the time it takes to complete each of these steps. Key strategies for optimization include:

  • Minimizing Render-Blocking Resources: Reduce the number of resources that block rendering, such as CSS and JavaScript files. Use techniques like minification, compression, and asynchronous loading to optimize resource delivery.
  • Prioritizing Above-the-Fold Content: Serve and render the most important content (above-the-fold) first to provide users with a meaningful initial view of the page while additional resources load in the background.
  • Optimizing CSS and JavaScript: Write efficient CSS and JavaScript code to minimize parsing and execution time. Use techniques like code splitting, lazy loading, and tree shaking to reduce file sizes and improve load times.
  • Caching and Compression: Leverage browser caching and compression techniques (e.g., gzip) to reduce network latency and speed up resource delivery.
  • Server-Side Rendering (SSR): Consider server-side rendering for dynamic web applications to generate HTML content on the server and deliver pre-rendered pages to the client, reducing the workload on the browser.

38. freeze method in JavaScript ?

In JavaScript, the Object.freeze() method is used to freeze an object, preventing any further modifications to its properties and preventing the addition or removal of properties. Once an object is frozen, its properties become immutable, meaning they cannot be changed, redefined, or deleted.

Here’s how you can use Object.freeze():

const obj = {
  prop1: 1,
  prop2: 'hello'
};

// Freeze the object
Object.freeze(obj);

// Attempt to modify a property
obj.prop1 = 2; // This change will not take effect
obj.prop2 = 'world'; // This change will not take effect

// Attempt to add a new property
obj.prop3 = true; // This addition will not take effect

// Attempt to delete a property
delete obj.prop1; // This deletion will not take effect

console.log(obj); // Output: { prop1: 1, prop2: 'hello' }

In this example, after Object.freeze(obj) is called, attempts to modify, add, or delete properties on the obj object are ignored. The object remains unchanged, and any such attempts do not have any effect.

Object.freeze() operates at the top level of an object and only makes the object itself immutable. If the object contains nested objects, those nested objects are not automatically frozen and can still be modified unless they are also explicitly frozen.

Keep in mind that Object.freeze() provides shallow immutability. This means that while the properties of the object itself become immutable, the values of any properties that are objects themselves (nested objects) are not affected by Object.freeze() and can still be modified unless they are also frozen.

const nestedObj = {
  inner: {
    prop: 'value'
  }
};

Object.freeze(nestedObj);

nestedObj.inner.prop = 'new value'; // This change will take effect

console.log(nestedObj.inner.prop); // Output: 'new value'

To achieve deep immutability, where all nested objects are also frozen, you would need to recursively apply Object.freeze() to all nested objects within the object hierarchy. Alternatively, you could use libraries like Immutable.js, which provide data structures with built-in immutability.

39. generator function in JavaScript ?

In JavaScript, a generator function is a special type of function that can pause its execution (“yield” values) and later resume from where it left off. This allows for more flexible control flow compared to regular functions, especially when dealing with asynchronous operations, iterating over large datasets, or implementing custom iterators.

Here’s how you define a generator function using the function* syntax:

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

const generator = myGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }

In this example:

  • function* myGenerator() defines a generator function named myGenerator.
  • Inside the function body, the yield keyword is used to pause the execution of the generator and return a value (1, 2, 3 in this case).
  • Each call to generator.next() resumes the execution of the generator until the next yield statement or until the end of the function. It returns an object with two properties: value (the yielded value) and done (a boolean indicating whether the generator has finished).

Generator functions provide several benefits:

  1. Lazy Evaluation: Values are produced on-demand, allowing for more efficient memory usage, especially when dealing with large datasets or infinite sequences.
  2. Asynchronous Operations: Generators can simplify asynchronous programming by abstracting away callback-based APIs or using yield with Promises to pause execution until asynchronous operations complete.
  3. State Management: Generator functions can maintain internal state between calls, allowing for more complex control flow patterns and custom iterators.
  4. Iterables and Iterators: Generator functions automatically create iterable objects that can be iterated over using for...of loops or by manually calling next().

Generators are a powerful tool in JavaScript for implementing complex control flows and handling asynchronous operations in a more readable and maintainable way. However, they require an understanding of how they work and may not be necessary for every use case.

40. Explain execution context and lexical environment in JavaScript ?

In JavaScript, execution context and lexical environment are closely related concepts that play a crucial role in understanding how JavaScript code is executed and how variables are scoped.

Lexical Environment:
A lexical environment is an internal data structure that holds information about the variables, functions, and their scopes at a particular point in the code. It consists of two components:

  1. Environment Record: This component stores variable bindings and function declarations within the current scope. It can be thought of as a mapping of identifiers to their values.
  2. Reference to Outer Environment: This component references the lexical environment of the enclosing (outer) scope, allowing for nested scopes and access to variables defined in outer scopes.

Execution Context:
An execution context is a runtime concept that represents the context in which JavaScript code is executed. It consists of:

  1. Lexical Environment: The lexical environment associated with the current code execution. It provides access to variables, functions, and their scopes within the current context.
  2. This Binding: The value of the this keyword within the current context, determined by how a function is called (e.g., as a method, with apply() or call(), or in strict mode).
  3. Variable Object (for Functions): In older JavaScript engines, a variable object was used to store local variables, function arguments, and inner function declarations within a function’s execution context. This concept is now largely replaced by the lexical environment.

When JavaScript code is executed, the runtime maintains a stack of execution contexts known as the “call stack.” Each time a function is called, a new execution context is created and pushed onto the stack. When the function returns, its execution context is popped off the stack, and control is returned to the previous context.

The lexical environment associated with the currently executing code is determined by the lexical scope, which is determined at the time the code is written (i.e., based on the physical placement of code within the source file). This is why JavaScript is often referred to as having “lexical scoping.”

Understanding execution context and lexical environment is crucial for understanding variable scope, closures, and how JavaScript code behaves at runtime. It forms the foundation for understanding more advanced concepts like closures, hoisting, and scope chaining.

Leave a Reply

Your email address will not be published. Required fields are marked *