FrontendDeveloper.in

ECMAScript Interview Questions

  • Question 61

    Class fields

    ES2015 introduced classes to javascript and class properties are defined in the constructor. In the below example, the Employee class has two fields defined in the constructor.

    class Employee  {
    
    constructor() {
    this.name = "John"; //public
    this._age=35; //private
    }
    
    const employee = new Employee();
    employee.name = "Jack";
    employee._age =35; //No error
    

    In the above example, the private _age property can be accessed and modified outside of the class. The prefix _ is just a naming convention for private field and won't enforce any strict rule.

    ES2022 introduced private and static fields to the classes.

    1. Public and private fields or methods: ES2022 introduced public and private properties or methods like other programming languages. These properties and methods can be defined outside the constructor and private fields prefixed with # symbol followed by variable name.

    In the below example, the Employee class has been defined with private variable outside the constructor.

    class Employee  {
    name = "John";
    #age=35;
    constructor() {
    }
    
    #getAge() {
    return #age
    }
    
    }
    
     const employee = new Employee();
     employee.name = "Jack";
     employee.#age = 35; // Throws an error
    
    1. Static fields and methods:

    Static fields and methods are applied to the class level and they can be accessed without an instance of a class. These fields and methods declared with static keyword

    Let's define a employee class with static field and methods declared with static keyword.

    class Employee{
    name = "John";
    static #employerName="Github"
    
    static #getEmployerName() {
    return #employerName
    }
    }
    const employee = new Employee();
    employee.emp = "Jack";
    employee.#employerName = 35; // Throws an error
    
    
  • Question 62

    Array .at() method

    The .at() method is used to access an array or string elements by passing the negative index value. i.e, It allows accessing values from the end of an array or from a string.

    Before ES2022, You should have to access the elements from the end as below,

    const array = [1, 2, 3, 4, 5];
    console.log(array[array.length - 2]); //4
    console.log(array.slice(-2)[0]); //4
    
    const string = '12345';
    console.log(string[string.length - 2]); // '4'
    console.log(string.slice(-2)[0]); // '4'
    

    Now you should be able to write:

    const array = [1, 2, 3, 4, 5];
    console.log(array.at(-2)); // 4
    
    const string = '12345';
    console.log(string.at(-2));
    
  • Question 63

    Error Cause

    The cause property is added to the Error() constructor as an extra parameter which allow errors to be chained similar to Java-like stack traces in error chains.

    In the below example, let's catch an error from JSON processing and re-throw it with a new meaningful message along with the original cause of the error.

    function processUserData(arrayData) {
    return arrayData.map(data => {
    try {
    const json = JSON.parse(data);
    return json;
    } catch (err) {
    throw new Error(
    `Data processing failed`,
    {cause: err}
    );
    }
    });
     }
    
  • Question 64

    hasOwn

    The new Object.hasOwn() method is a replacement or improved version of Object.prototype.hasOwnProperty. It is a static method that returns true if the specified object has the indicated property as its own property. If the property is inherited, or does not exist, the method returns false.

    It's not only more concise and readable but also overcomes the below limitations of hasOwnProperty.

    1. When hasOwnPropertyoverwritten:

    There are cases where you need to define customized hasOwnProperty on the object. When you try to apply hasOwnProperty to determine the own property or not, it throws an error as shown in below example.

    const user = {
    age: 35,
    hasOwnProperty: ()=> {
    return false;
    }
    };
    
    user.hasOwnProperty('age') // throws a TypeError
    

    This issue can be solved by hasOwn method .

    const user = {
    age: 35,
    hasOwnProperty: ()=> {
    return false;
    }
    };
    
    user.hasOwn('age') // true
    
    1. Create an object with create(null) function:

    If you create new object with help of create(null) function, then newly created object doesn’t inherit from Object.prototype. So it doesn't have hasOwnProperty method.

    Let's take an example to verify hasOwnProperty on an object created with create(null) function.

    const user = Object.create(null);
    user.age = 35;
    user.hasOwnProperty('age'); // throws a TypeError
    

    In this case, hasOwn() method can be used to determine the own property.

    const user = Object.create(null);
    user.age = 35;
    user.hasOwn('age'); // true
    
  • Question 65

    Regex match indices

    Regex match has been upgraded to include more information about the matching groups. The additional information includes starting and ending indices of matches in a RegExp with the usage of \d flag in the input string.

    Let's take an example of regex pattern on the input string without \d flag and the information of the matches.

    const regexPatter = /Jack/g;
    const input = 'Authos: Jack, Alexander and Jacky';
    const result = [...input.matchAll(regexPatter)];
    console.log(result[0]); // ['Jack', index: 8, input: 'Authos: Jack, Alex and Jacky', groups: undefined]
    

    Whereas \d flag provides an additional array with the indices of the different elements that match the regex,

    const regexPatter = /(Jack)/gd;
    const input = 'Authos: Jack, Alexander and Jacky';
    const result = [...input.matchAll(regexPatter)];
    console.log(result[0]); // ['Jack', 'Jack', index: 8, input: 'Authos: Jack, Alexander and Jacky', groups: undefined, indices: Array(2)]
    

    ES2023 Or ES14

    ECMAScript 2023 or ES14 has been released in the month of June 2023 with some of important features like adding new methods for searching and altering the arrays, supporting symbols as keys for WeakMap API and standardizing the hashbang syntax in JavaScript.

  • Question 66

    Find array from last

    This release introduced two new array methods named findLast() and findLastIndex() to search an array element from the last. Their functionality is similar to find() and findIndex() but searching starts from the end of an array. These methods are available on Array and TypedArray prototypes. This feature provides an efficient way for reverse order search by eliminating the process of manual array reversal.

    For example, let's see the usage of finding odd elements from end of an array prior to ES2023. There are no direct methods available to search element from end of an array. Hence, the array needs to be reversed first before applying first() and firstIndex() methods.

    const isOdd = (number) => number % 2 === 1;
    const numbers = [1, 2, 3, 4, 5];
    const reverseNumbers = [5, 4, 3, 2, 1];
    
    console.log(reverseNumbers.find(isOdd)); // 5
    console.log(reverseNumbers.findIndex(isOdd)); // 4
    

    This process is going to be simplified in ES2023 release using findLast() and findLastIndex() methods.

    const isOdd = (number) => number % 2 === 1;
    const numbers = [1, 2, 3, 4, 5];
    
    console.log(numbers.findLast(isOdd)); // 5
    console.log(numbers.findLastIndex(isOdd)); // 4
    
  • Question 67

    Hashbang syntax

    Hashbang(as known as shebang) grammar has been supported with a sequence of characters(#!) at the beginning of an executable script to define the interpreter for the program to run. In other words, this syntax is helpful to tell the operating system which interpreter to use while executing the script.

    For example, the below javascript file will be executed in NodeJS interpreter from Unix commandline.

    #!/usr/bin/env node
    'use strict';
    console.log("Hello world from hashbang syntax");
    
  • Question 68

    Symbols as weakmap keys

    Prior to ES2023, WeakMaps are only limited to allow objects as keys because objects are unique and cannot be re-created. Since symbols are the only primitives in ECMAScript that allows unique values, WeakMap API has been extended with symbols as keys instead of just using objects.

    As an example, the usage of WeakMap with objects as keys prior to ES2023 looks like below

    const weak = new WeakMap();
    const objKey = { x:10 };
    
    weak.set(objKey, "ES2023");
    console.log(weak.get(objKey)); //ES2023
    

    In ES2023, it is possible to use symbols as keys

    const weak = new WeakMap();
    const key = Symbol("ref");
    weak.set(key, "ES2023");
    
    console.log(weak.get(key)); //ES2023
    
  • Question 69

    Change array by copy

    Both Array and TypedArray has built-in methods such as reverse(), sort() and splice() to perform common actions like sorting, reverse the array elements and replacing(or removing) elements. But these methods are mutating the original array. Where as ES2023 has provided additional methods such as toReversed(), toSorted(), toSpliced and with() methods which returns new array copies instead of mutating the original array.

    For example, these additional methods returns new array copies for number array without mutating the original array as shown below,

    const numbers = [1, 3, 2, 4, 5];
    
    // toReversed
    const reversedArray = numbers.toReversed();
    console.log(reversedArray); // [5, 4, 2, 3, 1]
    console.log(numbers); // [1, 3, 2, 4, 5]
    
    // toSorted
    const sortedArray = numbers.toSorted();
    console.log(sortedArray); // [1, 2, 3, 4, 5]
    console.log(numbers); // [1, 3, 2, 4, 5]
    
    // toSpliced
    const splicedArray = numbers.toSpliced(1, 3);
    console.log(splicedArray); // [1, 5]
    console.log(numbers); // [1, 3, 2, 4, 5]
    
    // with
    const replaceWithArray = numbers.with(2, 10);
    console.log(replaceWithArray); // [1, 3, 10, 4, 5]
    console.log(numbers); // [1, 3, 2, 4, 5]
    

    ES2024 or ES15

    ES2024 is planned to be release in June 2024 with a couple of features and enhancements for the developers to make coding in JavaScript more efficient, readable, and robust.

  • Question 70

    GroupBy into objects and maps:

    The Object.groupBy() method is used to group object elements of an iterable(like array) based on string values returned from a callback function. It returns an object with each group name as key and respective array of elements as value. The elements in the returned object and the original object are the same. i.e, If you change the internal structure of the elements, it will be reflected in both original and returned object.

    In the following example, persons are into categories into several groups based on their age.

    const persons = [
    {name:"John", age:70},
    {name:"Kane", age:5},
    {name:"Jack", age:50},
    {name:"Rambo", age:15}
    ];
    
    // Callback function to categorize people based on age
    function callbackFunc({ age }) {
    if(age >= 60) {
    return "senior";
    } else if(age > 17 && age < 60) {
    return "adult";
    }
    else {
    return "kid";
    }
    }
    
    const result = Object.groupBy(persons, callbackFunc);
    
    console.log("Kids: ");
    for (let [x,y] of result.kid.entries()) {
    console.log(y.name + " " + y.age);
    }
    
    console.log("Adults: ");
    for (let [x,y] of result.adult.entries()) {
    console.log(y.name + " " + y.age);
    }
    
    console.log("Seniors: ");
    for (let [x,y] of result.senior.entries()) {
    console.log(y.name + " " + y.age);
    }
    

    The Map.groupBy() method is also used to group elements of an object but the result is in the form of a map.

    const persons = [
    {name:"John", age:70},
    {name:"Kane", age:5},
    {name:"Jack", age:50},
    {name:"Rambo", age:15}
    ];
    
    // Callback function to categorize people based on age
    function callbackFunc({ age }) {
    if(age >= 60) {
    return "senior";
    } else if(age > 17 && age < 60) {
    return "adult";
    }
    else {
    return "kid";
    }
    }
    
    const result = Map.groupBy(persons, callbackFunc);
    
    console.log("Kids: ");
    for (let x of result.get("kid")) {
    console.log(x.name + " " + x.age);
    }
    
    console.log("Adults: ");
    for (let x of result.get("adult")) {
    console.log(x.name + " " + x.age);
    }
    
    console.log("Seniors: ");
    for (let x of result.get("senior")) {
    console.log(x.name + " " + x.age);
    }
    
  • Question 71

    Temporal API

    The Temporal API is a modern API for working with dates and times, used to supersede the original Date API. It provides a more comprehensive and user-friendly way to handle date and time manipulation.

    It contains the following core objects,

    1. Temporal.PlainDate
    2. Temporal.PlainTime
    3. Temporal.PlainDateTime
    4. Temporal.PlainYearMonth
    5. Temporal.PlainMonthDay
    6. Temporal.ZonedDateTime
  • Question 72

    Well formed unicode strings

    Unicode strings are mainly used for representing a wide range of characters from different languages and symbols. In UTF-16, strings which contain lone surrogates(16-bit Code Unit) are considered as "malformed" or "not well formatted". These lone surrogates can be of two types,

    1. Leading surrogates: Range between 0XD800 to 0XDBFF
    2. Trailing Surrogate: Range between 0XDC00 to 0XDFFF

    Well-Formed Unicode Strings feature introduced below two string methods to check and convert into wellformed strings.

    1. String.prototype.isWellFormed: This method is used to check if the string contains lone surrogates or not. Returns true, if unicode string is not present. The following stings can be verified either as well-formed or not well-formed strings,
    const str1 = "Hello World \uD815";
    const str2 = "Welcome to ES2024";
    const str3 = "Welcome to ES2024 😀";
    
    console.log(str1.isWellFormed()); // false
    console.log(str2.isWellFormed()); // true
    console.log(str2.isWellFormed()); // true
    

    Note: Emojis are considered as well-formed unicode strings.

    1. String.prototype.toWellFormed: This method is used to return a string by converting unpaired surrogate(i.e, leading and trailing surrogates) code points with U+FFFD Replacement characters.
    const str1 = "Hello World \uD815";
    const str2 = "Welcome to ES2024";
    
    console.log(str1.toWellFormed()); // Hello World �
    console.log(str2.toWellFormed()); // Welcome to ES2024
    

    These two methods are mainly helpful for developers to work with string encoding without any errors. For example, the below encoding process throws an error due to lone surrogates,

    const url = "https://somedomain.com/query=\uD423";
    
    try {
    console.log(encodeURI(url));
    } catch (e) {
    console.log('Error:', e.message); // Expected: URIError: URI malformed
    }
    

    After applying toWellFormed() method, the lone surrogate is replaced with the Unicode replacement character (U+FFFD). It make sure encodeURI() is processed without errors.

    console.log(encodeURI(url.toWellFormed())); // https://somedomain.com/query=%ED%90%A3
    
  • Question 73

    Atomic waitSync

    The Atomics.waitAsync() is a static method that waits asynchronously on a shared memory location and returns a Promise. It is non-blocking as compared to Atomics.wait() and can be used on the main thread. The syntax looks like below,

    Atomics.waitAsync(typedArray, ind, val, timeOut);
    

    If the promise is not fulfilled then it will lead to a 'time-out' status otherwise the status will always be 'ok' once the promise has been fulfilled.

    Let's take a shared Int32Array. Here it waits asynchronously for position 0 and expects a result 0 waiting for 500ms.

    const arrayBuffer = new SharedArrayBuffer(1024);
    const arr = new Int32Array(arrayBuffer);
    
    Atomics.waitAsync(arr, 0 , 0 , 500); // { async: true, value: Promise {<pending>}}
    
    Atomics.notify(arr, 0); // { async: true, value: Promise {<fulfilled>: 'ok'} }
    

    After that, the notify method awakes the waiting agent(i.e, array) that are sleeping in waiting queue and the promise is fulfilled.

    Remember that, SharedArrayBuffer have been disabled on most browsers unless you specify Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers. For example,

    Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp

    Note: There will be a TypeError if typedArray is not an Int32Array or BigInt64Array that views a SharedArrayBuffer.

  • Question 74

    Promise withResolvers

    When you are creating a new Promise object, usually you pass resolve and reject functions to the executor of promise constructor as shown below:

    const promise = new Promise((resolve, reject) =>{
    setTimeout(() =>  { Math.random() > 0.5 ? resolve("Success") : reject("Error")}, 1000);
    });
    promise.then(result => console.log(result)).catch(error => console.error(error));
    

    In this constructor pattern, it is possible call the resolve and reject functions inside the promise constructor only. But if you want these functions outside of the promise constructor, you often have to write the following boilerplate code.

    let resolve, reject;
    const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
    });
    
    setTimeout(() =>  { Math.random() > 0.5 ? resolve("Success") : reject("Error")}, 1000);
    promise.then(result => console.log(result)).catch(error => console.error(error));
    

    The above code is simplified with Promise.withResolvers() in ES2024, it's a static method factory that returns an object containing a new Promise along with two functions one for resolve and other one for reject. These two functions corresponding to the two parameters passed to the executor of the Promise() constructor shown in the initial code snippets.

    The concise version of earlier code snippet looks like below,

    const { promise, resolve, reject} = Promise.withResolvers();
    
    setTimeout(() =>  { Math.random() > 0.5 ? resolve("Success") : reject("Error")},1000);
    promise.then(result => console.log(result)).catch(error => console.error(error));
    

    ES2025 or ES16

    ES2025 is planned to be released in June 2025 with several new features and enhancements for JavaScript developers. These features aim to improve developer productivity and code readability.

  • Question 75

    Set Methods

    ES2025 introduces several new methods to the Set prototype that make working with sets more convenient and expressive. These methods provide operations commonly found in set theory, such as union, intersection, and difference.

    // Create some sample sets
    const set1 = new Set([1, 2, 3, 4, 5]);
    const set2 = new Set([3, 4, 5, 6, 7]);
    
    // Union - combines elements from both sets
    const union = set1.union(set2);
    console.log([...union]); // [1, 2, 3, 4, 5, 6, 7]
    
    // Intersection - elements present in both sets
    const intersection = set1.intersection(set2);
    console.log([...intersection]); // [3, 4, 5]
    
    // Difference - elements in first set but not in second
    const difference = set1.difference(set2);
    console.log([...difference]); // [1, 2]
    
    // Symmetric Difference - elements in either set but not in both
    const symDifference = set1.symmetricDifference(set2);
    console.log([...symDifference]); // [1, 2, 6, 7]
    

    The new Set methods include:

    1. Set.prototype.union(): Returns a new Set containing all elements from both sets.
    2. Set.prototype.intersection(): Returns a new Set containing elements present in all sets.
    3. Set.prototype.difference(): Returns a new Set containing elements present in the first set but not in the second.
    4. Set.prototype.symmetricDifference(): Returns a new Set containing elements present in either set but not in both.
    5. Set.prototype.isSubsetOf(): Returns a boolean indicating if the set is a subset of the given set.
    6. Set.prototype.isSupersetOf(): Returns a boolean indicating if the set is a superset of the given set.
    7. Set.prototype.isDisjointFrom(): Returns a boolean indicating if the set has no elements in common with the given set.

    These methods can be particularly useful for data processing, filtering, and comparison operations.

    // Practical example: Finding common interests between users
    const user1Interests = new Set(["coding", "reading", "music", "hiking"]);
    const user2Interests = new Set(["gaming", "music", "movies", "hiking"]);
    
    // Find common interests
    const commonInterests = user1Interests.intersection(user2Interests);
    console.log([...commonInterests]); // ["music", "hiking"]
    
    // Find unique interests of user1
    const uniqueInterests = user1Interests.difference(user2Interests);
    console.log([...uniqueInterests]); // ["coding", "reading"]
    
Get LinkedIn Premium at Rs 399