Javascript Interview questions – New features

1. What are template literals in JavaScript, and how do they differ from traditional strings?

Answer:
Template literals are a feature introduced in ECMAScript 6 (ES6) that allow you to create strings with embedded expressions. They are enclosed in backticks (`) instead of single or double quotes. Template literals are more flexible and concise than traditional strings because they allow for multiline strings and the interpolation of variables and expressions using ${}.

Example:

JavaScript
   const name = "John";
   const age = 30;

   // Template literal
   const greeting = `Hello, my name is ${name} and I am ${age} years old.`;

   // Traditional string concatenation
   const traditionalGreeting = "Hello, my name is " + name + " and I am " + age + " years old.";

In this example, the template literal is more readable and allows for easy variable interpolation.

2. What are arrow functions, and how do they differ from regular functions?

Answer:
Arrow functions are a feature introduced in ES6 that provide a more concise syntax for defining functions in JavaScript. They differ from regular functions in a few key ways:

  • Syntax: Arrow functions have a shorter and more straightforward syntax.
  • this Binding: Arrow functions do not have their own this binding; instead, they inherit the this value from their enclosing lexical (surrounding) scope.
  • No Arguments Object: Arrow functions do not have their own arguments object. Example:
JavaScript
   // Regular function
   function add(a, b) {
     return a + b;
   }

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

Arrow functions are often preferred for simple functions, especially when you want to maintain the this context of the surrounding code.

3. What is the purpose of the “let” and “const” keywords in ES6 for variable declaration?

Answer:
In ES6, the let and const keywords were introduced to provide block-scoped variable declarations, replacing the behavior of the var keyword. Here’s how they differ:

  • let: Variables declared with let have block scope, meaning they are only accessible within the block (enclosed by {}) where they are defined. They can also be reassigned new values within the same block scope.
  • const: Variables declared with const also have block scope but come with an additional constraint: they cannot be reassigned after their initial value is set. However, they can still be mutated if they hold objects or arrays (the variable itself remains constant, not the object it references). Examples:
JavaScript
   function example() {
     if (true) {
       let x = 10; // Block-scoped variable
       const y = 20; // Block-scoped constant
       x = 30; // Reassignment is allowed
       // y = 40; // Error: Cannot reassign a constant variable
     }
     // console.log(x); // Error: x is not defined (out of scope)
     // console.log(y); // Error: y is not defined (out of scope)
   }

4. What are destructuring assignment and how can they be used in JavaScript?

Answer:
Destructuring assignment is a feature introduced in ES6 that provides a concise way to extract values from objects and arrays and assign them to variables. It simplifies variable assignment and can be used with objects, arrays, and nested structures.

Object Destructuring:

JavaScript
   const person = { name: "John", age: 30 };
   const { name, age } = person; // Extracts properties into variables

Array Destructuring:

JavaScript
   const numbers = [1, 2, 3];
   const [first, second, third] = numbers; // Extracts array elements into variables

Destructuring assignment can also be used in function parameters and with default values.

5. Explain the “spread” and “rest” operators introduced in ES6.

Answer:

  • Spread Operator (...): The spread operator allows you to spread the elements of an iterable (e.g., an array) into another array or object. It is used for copying or merging values and is particularly useful for creating new arrays or objects without modifying the original. Example (Spread Operator):
JavaScript
   const arr1 = [1, 2, 3];
   const arr2 = [...arr1, 4, 5]; // Creates a new array by spreading elements
  • Rest Operator (...): The rest operator is used in function parameters to collect remaining arguments into an array. It enables functions to accept a variable number of arguments without explicitly specifying them. Example (Rest Operator):
JavaScript
   function sum(...numbers) {
     return numbers.reduce((acc, num) => acc + num, 0);
   }

Both operators enhance the flexibility and readability of code in various scenarios.

6. What is the purpose of the “class” keyword in ES6, and how does it simplify object-oriented programming in JavaScript?

Answer:
The class keyword introduced in ES6 allows developers to define classes, which are templates for creating objects with shared properties and methods. Classes simplify object-oriented programming in JavaScript by providing a more structured and familiar syntax for defining constructor functions and inheritance hierarchies.

Example:

JavaScript
   class Person {
     constructor(name) {
       this.name = name;
     }

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

   const john = new Person("John");
   john.greet(); // "Hello, John!"

In this example, the Person class serves as a blueprint for creating person objects with a name property and a greet method.

7. What are Promises in JavaScript, and how do they simplify asynchronous code handling?

Answer:
Promises are a feature introduced in ES6 to simplify asynchronous code handling by providing a more structured way to work with asynchronous operations. A Promise represents the eventual completion (or failure) of an asynchronous task and allows you to handle the result or error when it becomes available.

Promises have three states:

  • Pending: Initial state before the task is completed.
  • Fulfilled: The task completed successfully, and the result is available.
  • Rejected: The task encountered an error, and an error reason is available. Example:
JavaScript
   function fetchData() {
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         const data = "Data fetched successfully";
         resolve(data); // Resolve the promise with data
         // If an error occurs, use: reject(error

);
       }, 1000);
     });
   }

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

Promises simplify asynchronous code by allowing you to chain .then() and .catch() handlers to handle success and error cases, respectively.

8. What is the “async/await” feature in JavaScript, and how does it simplify asynchronous code?

Answer:
async/await is a feature introduced in ES2017 (ES8) that simplifies asynchronous code by making it appear more synchronous and readable. It allows you to write asynchronous code using a more linear and structured syntax, similar to traditional synchronous code.

  • async: The async keyword is used to define an asynchronous function. An asynchronous function returns a Promise implicitly, allowing you to use await within it.
  • await: The await keyword is used inside an asynchronous function to pause the execution until a Promise is resolved. It can only be used within an asynchronous function. Example:
JavaScript
   async function fetchData() {
     try {
       const response = await fetch("https://api.example.com/data");
       const data = await response.json();
       return data;
     } catch (error) {
       console.error("Error fetching data:", error);
       throw error;
     }
   }

async/await simplifies error handling and improves the readability of asynchronous code by making it resemble synchronous code flow.

9. What is the purpose of the “map” and “filter” array methods introduced in ES6? Provide examples.

Answer:

  • map Method: The map() method is used to create a new array by applying a provided function to each element of an existing array. It returns a new array with the results of the applied function. Example (map):
JavaScript
   const numbers = [1, 2, 3];
   const doubled = numbers.map((num) => num * 2); // Creates a new array with doubled values
  • filter Method: The filter() method is used to create a new array with all elements that pass a test defined by a provided function. It returns a new array containing only the elements that meet the criteria. Example (filter):
JavaScript
   const numbers = [1, 2, 3, 4, 5];
   const evenNumbers = numbers.filter((num) => num % 2 === 0); // Creates a new array with even numbers

These array methods simplify the process of transforming and filtering arrays, making code more concise and expressive.

10. What are the “let” and “const” keywords for block-scoped variables introduced in ES6, and how do they differ from “var”?

Answer:

  • let and const: Both let and const are used for declaring variables with block scope, which means they are only accessible within the block (enclosed by {}) where they are defined.
  • let: Variables declared with let can be reassigned new values within the same block scope, making them mutable.
  • const: Variables declared with const also have block scope but cannot be reassigned after their initial value is set. However, they can still be mutated if they hold objects or arrays (the variable itself remains constant, not the object it references). Examples:
JavaScript
   function example() {
     if (true) {
       let x = 10; // Block-scoped variable
       const y = 20; // Block-scoped constant
       x = 30; // Reassignment is allowed for 'let'
       // y = 40; // Error: Cannot reassign a constant variable
     }
     // console.log(x); // Error: x is not defined (out of scope)
     // console.log(y); // Error: y is not defined (out of scope)
   }

The introduction of let and const improves variable scoping and reduces the risk of unintended variable modifications compared to the previous behavior of var.

11. What are the rest and spread properties introduced in ES6 for objects, and how do they work?

Answer:
In ES6, rest and spread properties were introduced for objects. They provide a concise way to work with object properties.

  • Rest Properties (...): Rest properties allow you to collect the remaining properties of an object into a single variable. This is especially useful when you want to destructure an object while keeping the remaining properties intact. Example (Rest Properties):
JavaScript
   const { x, y, ...rest } = { x: 1, y: 2, z: 3, a: 4 };
   console.log(rest); // { z: 3, a: 4 }
  • Spread Properties (...): Spread properties allow you to merge the properties of one object into another object. It is a convenient way to clone or combine objects. Example (Spread Properties):
JavaScript
   const obj1 = { x: 1, y: 2 };
   const obj2 = { ...obj1, z: 3 };
   console.log(obj2); // { x: 1, y: 2, z: 3 }

Rest and spread properties improve the flexibility and maintainability of code when working with objects.

12. What is a Set in JavaScript, and how does it differ from an Array?

Answer:
A Set is a built-in data structure introduced in ES6 that represents a collection of unique values. Unlike an Array, which can contain duplicate values and is ordered, a Set only stores unique values and does not guarantee a specific order of elements.

Example (Set):

JavaScript
   const mySet = new Set();
   mySet.add(1);
   mySet.add(2);
   mySet.add(1); // Duplicate value, not added

   console.log(mySet); // Set { 1, 2 }

Sets are useful when you need to ensure uniqueness and do not require a specific order for elements.

13. What are generators in JavaScript, and how do they work?

Answer:
Generators are a special type of function introduced in ES6 that allow you to pause and resume the execution of a function. They are defined using an asterisk (*) after the function keyword and contain one or more yield statements to yield values. Generators are iterables and can be used to create custom iterable objects.

Example (Generator):

JavaScript
   function* generateNumbers() {
     yield 1;
     yield 2;
     yield 3;
   }

   const numbers = generateNumbers();
   console.log(numbers.next().value); // 1
   console.log(numbers.next().value); // 2
   console.log(numbers.next().value); // 3

Generators are useful for creating iterators and handling asynchronous code in a more readable and synchronous-like manner.

14. What is the “Proxy” object in JavaScript, and how can it be used to intercept and customize object operations?

Answer:
The Proxy object is an ES6 feature that allows you to intercept and customize fundamental operations on objects, such as property access, assignment, function invocation, and more. It provides a way to define custom behavior when interacting with objects, making it useful for creating advanced abstractions and security features.

Example (Proxy):

JavaScript
   const target = {
     name: "John",
     age: 30,
   };

   const handler = {
     get: function (target, prop) {
       if (prop in target) {
         return target[prop];
       } else {
         throw new Error(`Property '${prop}' not found.`);
       }
     },
   };

   const proxy = new Proxy(target, handler);
   console.log(proxy.name); // "John"
   console.log(proxy.country); // Error: Property 'country' not found.

In this example, the Proxy intercepts property access and throws an error for non-existent properties.

15. What is the “Promise.all” method in JavaScript, and how does it work?

Answer:
Promise.all is a built-in method in JavaScript that allows you to handle multiple promises concurrently and wait for all of them to either resolve or reject. It takes an iterable (e.g., an array) of promises as input and returns a new promise. The new promise resolves with an array of results when all input promises have resolved, or it rejects with the first encountered rejection reason.

Example (Promise.all):

JavaScript
   const promise1 = fetch("https://api.example.com/data/1");
   const promise2 = fetch("https://api.example.com/data/2");

   Promise.all([promise1, promise2])
     .then((responses) => {
       // Handle responses
       const data1 = responses[0].json();
       const data2 = responses[1].json();
       return Promise.all([data1, data2]);
     })
     .then(([data1, data2]) => {
       console.log(data1, data2);
     })
     .catch((error) => {
       console.error("Error:", error);
     });

Promise.all is useful for situations where you need to perform multiple asynchronous operations and wait for all of them to complete before proceeding.

Leave a Comment

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

Scroll to Top