FrontendDeveloper.in

ECMAScript Interview Questions

  • Question 31

    String padding

    Some strings and numbers(money, date, timers etc) need to be represented in a particular format. Both padStart() & padEnd() methods introduced to pad a string with another string until the resulting string reaches the supplied length.

    1. padStart(): Using this method, padding is applied to the left or beginning side of the string.

    For example, you may want to show only the last four digits of credit card number for security reasons,

    const cardNumber = '01234567891234';
    const lastFourDigits = cardNumber.slice(-4);
    const maskedCardNumber = lastFourDigits.padStart(cardNumber.length, '*');
    console.log(maskedCardNumber); // expected output: "**********1234"
    
    1. padEnd(): Using this method, padding is applied to the right or ending side of the string.

    For example, the profile information padded for label and values as below

    const label1 = "Name";
    const label2 = "Phone Number";
    const value1 = "John"
    const value2 = "(222)-333-3456";
    
    console.log((label1 + ': ').padEnd(20, ' ') + value1); // Name:                     John
    console.log(label2 + ": " + value2); // Phone Number: (222)-333-3456
    
  • Question 32

    Shared memory and atomics

    The Atomics is a global object which provides atomic operations to be performed as static methods. They are used with SharedArrayBuffer(fixed-length binary data buffer) objects. The main use cases of these methods are,

    1. atomic operations: When memory is shared, multiple threads can read and write the same data in memory. So there would be a chance of loss of data. But atomic operations make sure that predictable values are written and read, that operations are finished before the next operation starts and that operations are not interrupted.

    It provides static methods such as add, or, and, xor, load, store, isLockFree etc as demonstrated below.

    const sharedMemory = new SharedArrayBuffer(1024);
    const sharedArray = new Uint8Array(sharedMemory);
    sharedArray[0] = 10;
    
    Atomics.add(sharedArray, 0, 20);
    console.log(Atomics.load(sharedArray, 0)); // 30
    
    Atomics.sub(sharedArray, 0, 10);
    console.log(Atomics.load(sharedArray, 0)); // 20
    
    Atomics.and(sharedArray, 0, 5);
    console.log(Atomics.load(sharedArray, 0));  // 4
    
    Atomics.or(sharedArray, 0, 1);
    console.log(Atomics.load(sharedArray, 0));  // 5
    
    Atomics.xor(sharedArray, 0, 1);
    console.log(Atomics.load(sharedArray, 0)); // 4
    
    Atomics.store(sharedArray, 0, 10); // 10
    
    Atomics.compareExchange(sharedArray, 0, 5, 10);
    console.log(Atomics.load(sharedArray, 0)); // 10
    
    Atomics.exchange(sharedArray, 0, 10);
    console.log(Atomics.load(sharedArray, 0)); //10
    
    Atomics.isLockFree(1); // true
    
    1. waiting to be notified: Both wait() and notify() methods provides ways for waiting until a certain condition becomes true and are typically used as blocking constructs.

    Let's demonstrate this functionality with reading and writing threads.

    First define a shared memory and array

    const sharedMemory = new SharedArrayBuffer(1024);
    const sharedArray = new Int32Array(sharedMemory);
    

    A reading thread is sleeping and waiting on location 0 which is expected to be 10. You can observe a different value after the value overwritten by a writing thread.

    Atomics.wait(sharedArray, 0, 10);
    console.log(sharedArray[0]); // 100
    

    Now a writing thread stores a new value(e.g, 100) and notifies the waiting thread,

    Atomics.store(sharedArray, 0, 100);
    Atomics.notify(sharedArray, 0, 1);
    
  • Question 33

    Trailing commas

    Trailing commas are allowed in parameter definitions and function calls

     function func(a,b,) { // declaration
    console.log(a, b);
     }
    func(1,2,); // invocation
    

    But if the function parameter definition or function call only contains a comma, a syntax error will be thrown

     function func1(,) {  // SyntaxError: missing formal parameter
    console.log('no args');
     };
    func1(,); // SyntaxError: expected expression, got ','
    

    Note: Trailing commas are not allowed in Rest Parameters and JSON.

    ES2018 Or ES9

  • Question 34

    Async iterators

    ECMAScript 6 provides built-in support for synchronously iterating over data using iterators. Both strings and collections objects such as Set, Map, and Array come with a Symbol.iterator property which makes them iterable.

    const arr = ['a', 'b', 'c', 'd'];
    const syncIterator = arr[Symbol.iterator]();
    
    console.log(syncIterator.next()); // {value: a, done: false}
    console.log(syncIterator.next()); // {value: b, done: false}
    console.log(syncIterator.next()); // {value: c, done: false}
    console.log(syncIterator.next()); // {value: d, done: false}
    console.log(syncIterator.next()); // {value: undefined, done: true}
    

    But these iterators are only suitable for representing synchronous data sources.

    In order to access asynchronous data sources, ES2018 introduced the AsyncIterator interface, an asynchronous iteration statement (for-await-of), and async generator functions.

  • Question 35

    Object rest and spread operators

    ES2015 or ES6 introduced both rest parameters and spread operators to convert arguments to array and vice versa using three-dot(...) notation.

    1. Rest parameters can be used to convert function arguments to an array
     function myfunc(p1, p2, ...p3) {
    console.log(p1, p2, p3); // 1, 2, [3, 4, 5, 6]
     }
    myfunc(1, 2, 3, 4, 5, 6);
    
    1. The spread operator works in the opposite way by converting an array into separate arguments in order to pass to a function
    const myArray = [10, 5, 25, -100, 200, -200];
    console.log( Math.max(...myArray) ); // 200
    

    ES2018 enables this rest/spread behavior for objects as well.

    1. You can pass object to a function
    function myfunc1({ a, ...x }) {
    console.log(a, x); // 1, { b: 2, c: 3, d:4 }
    }
    myfunc1({
    a: 1,
    b: 2,
    c: 3,
    d: 4
    });
    
    1. The spread operator can be used within other objects
    const myObject = { a: 1, b: 2, c: 3, d:4 };
    const myNewObject = { ...myObject, e: 5 }; // { a: 1, b: 2, c: 3, d: 4, e: 5 }
    
  • Question 36

    Promise finally

    Sometimes you may need to avoid duplicate code in the then() and catch() methods.

    myPromise
    .then(result => {
    // process the result and then clean up the resources
    })
    .catch(error => {
    // handle the error and then clean up the resources
    });
    

    The finally() method is useful if you want to do some processing or resource cleanup once the promise is settled(i.e either fulfilled or rejected).

    Let's take a below example to hide the loading spinner after the data is fetched and processed.

    let isLoading = true;
    fetch('http://somesite.com/users')
    .then(data => data.json())
    .catch(err => console.error(err))
    .finally(() => {
    isLoading = false;
    console.log('Finished loading!!');
    })
    

    ES2019 Or ES10

  • Question 37

    Array flat and flatMap

    Prior to ES2019, you need to use reduce() or concat() methods to get a flat array.

    function flatten(arr) {
    const flat = [].concat(...arr);
    return flat.some(Array.isArray) ? flatten(flat) : flat;
    }
    flatten([ [1, 2, 3], ['one', 'two', 'three', [22, 33] ], ['a', 'b', 'c'] ]);
    

    In ES2019, the flat() method is introduced to 'flattens' the nested arrays into the top-level array. The functionality of this method is similar to Lodash's _.flattenDepth() function. This method accepts an optional argument that specifies the number of levels a nested array should be flattened and the default nested level is 1. Note: If there are any empty slots in the array, they will be discarded.

    const numberArray = [[1, 2], [[3], 4], [5, 6]];
    const charArray = ['a', , 'b', , , ['c', 'd'], 'e'];
    const flattenedArrOneLevel = numberArray.flat(1);
    const flattenedArrTwoLevel = numberArray.flat(2);
    const flattenedCharArrOneLevel = charArray.flat(1);
    
    console.log(flattenedArrOneLevel); // [1, 2, [3], 4, 5, 6]
    console.log(flattenedArrTwoLevel); // [1, 2, 3, 4, 5, 6]
    console.log(flattenedCharArrOneLevel); // ['a', 'b', 'c', 'd', 'e']
    

    Whereas, flatMap() method combines map() and flat() into one method. It first creates a new array with the return value of a given function and then concatenates all sub-array elements of the array.

    const numberArray1 = [[1], [2], [3], [4], [5]];
    
    console.log(numberArray1.flatMap(value => [value * 10])); // [10, 20, 30, 40, 50]
    
  • Question 38

    Object fromEntries

    In JavaScript, it is very common to transforming data from one format. ES2017 introduced Object.entries() method to objects into arrays.

    Object to Array:

    const obj = {'a': '1', 'b': '2', 'c': '3' };
    const arr = Object.entries(obj);
    console.log(arr); // [ ['a', '1'], ['b', '2'], ['c', '3'] ]
    

    But if you want to get the object back from an array then you need iterate and convert it as below,

    const arr = [ ['a', '1'], ['b', '2'], ['c', '3'] ];
    let obj = {}
    for (let [key, val] of arr) {
    obj[key] = val;
    }
    console.log(obj);
    

    We need a straightforward way to avoid this iteration. In ES2019, Object.fromEntries() method is introduced which performs the reverse of Object.entries() behavior. The above loop can be avoided easily as below,

    Iterable( e.g Array or Map) to Object

    const arr = [ ['a', '1'], ['b', '2'], ['c', '3'] ];
    const obj = Object.fromEntries(arr);
    console.log(obj); // { a: "1", b: "2", c: "3" }
    

    One of the common case of this method usage is working with query params of an URL,

    const paramsString = 'param1=foo&param2=baz';
    const searchParams = new URLSearchParams(paramsString);
    
    Object.fromEntries(searchParams);    // => {param1: "foo", param2: "baz"}
    
  • Question 39

    String trimStart and trimEnd

    In order to make consistency with padStart/padEnd, ES2019 provided the standard functions named as trimStart and trimEnd to trim white spaces on the beginning and ending of a string. However for web compatibility(avoid any breakage) trimLeft and trimRight will be an alias for trimStart and trimEnd respectively.

    Let's see the usage with an example,

    //Prior ES2019
    let messageOne = "   Hello World!!    ";
    console.log(messageOne.trimLeft()); //Hello World!!
    console.log(messageOne.trimRight()); //   Hello World!!
    
    //With ES2019
    let messageTwo = "   Hello World!!    ";
    console.log(messageTwo.trimStart()); //Hello World!!
    console.log(messageTwo.trimEnd()); //   Hello World!!
    
  • Question 40

    Symbol description

    While creating symbols, you also can add a description to it for debugging purposes. But there was no method to access the description directly before ES2019. Considering this, ES2019 introduced a read-only description property to retrieve a string containing the description of the Symbol.

    This gives the possibility to access symbol description for different variations of Symbol objects

    console.log(Symbol('one').description); // one
    
    console.log(Symbol.for('one').description); // "one"
    
    console.log(Symbol('').description); // ''
    
    console.log(Symbol().description); // undefined
    
    console.log(Symbol.iterator.description); // "Symbol.iterator"
    
  • Question 41

    Optional catch binding

    Prior to ES9, if you don't need error variable and omit the same variable then catch() clause won't be invoked. Also, the linters complain about unused variables. Inorder to avoid this problem, the optional catch binding feature is introduced to make the binding parameter optional in the catch clause. If you want to completely ignore the error or you already know the error but you just want to react to that the this feature is going to be useful.

    Let's see the below syntax difference between the versions,

    // With binding parameter(<ES9)
    try {
    ···
    } catch (error) {
    ···
    }
    // Without binding parameter(ES9)
    try {
    ···
    } catch {
    ···
    }
    

    For example, the feature detection on a browser is one of the most common case

    let isTheFeatureImplemented = false;
    try {
    if(isFeatureSupported()) {
    isTheFeatureImplemented = true;
    }
    } catch (unused) {}
    
  • Question 42

    JSON Improvements

    JSON is used as a lightweight format for data interchange(to read and parse). The usage of JSON has been improved as part of ECMAScript specification. Basically there are 2 important changes related to JSON.

    1. JSON Superset

    Prior to ES2019, ECMAScript claims JSON as a subset in JSON.parse but that is not true. Because ECMAScript string literals couldn’t contain the characters U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH SEPARATOR) unlike JSON Strings. If you still use those characters then there will be a syntax error. As a workaround, you had to use an escape sequence to put them into a string.

    eval('"\u2028"'); // SyntaxError
    

    Whereas JSON strings can contain both U+2028 and U+2029 without producing errors.​

    console.log(JSON.parse('"\u2028"')); // ''
    

    This restriction has been removed in ES2019. This simplifies the specification without the need of separate rules for ECMAScript string literals and JSON string literals.

    1. Well Formed JSON.Stringify(): Prior to ES2019, JSON.stringify method is used to return unformed Unicode strings(ill-formed Unicode strings) if there are any lone surrogates in the input.
    console.log(JSON.stringify("\uD800")); // '"�"'
    

    Whereas in ES2019, JSON.stringify outputs escape sequences for lone surrogates, making its output valid Unicode and representable in UTF-8.

    console.log(JSON.stringify("\uD800")); // '"\ud800"'
    
  • Question 43

    Array Stable Sort

    The sort method for arrays is stable in ES2020. i.e, If you have an array of objects and sort them on a given key, the elements in the list will retain their position relative to the other objects with the same key.​ Now the array is using the stable TimSort algorithm for arrays over 10 elements instead of the unstable QuickSort.

    Let's see an example of users retain their original position with same age group.

    const users = [
    { name: "Albert",  age: 30 },
    { name: "Bravo",   age: 30 },
    { name: "Colin",   age: 30 },
    { name: "Rock",    age: 50 },
    { name: "Sunny",   age: 50 },
    { name: "Talor",    age: 50 },
    { name: "John",   age: 25 },
    { name: "Kindo",  age: 25 },
    { name: "Lary",   age: 25 },
    { name: "Minjie",   age: 25 },
    { name: "Nova",    age: 25 }
    ]
    users.sort((a, b) => a.age - b.age);
    
  • Question 44

    Function.toString()

    Functions have an instance method called toString() which return a string to represent the function code. Previous versions of ECMAScript removes white spaces,new lines and comments from the function code but it has been retained with original source code in ES2020.

    function sayHello(message) {
    let msg = message;
    //Print message
    console.log(`Hello, ${msg}`);
    }
    
    console.log(sayHello.toString());
    // function sayHello(message) {
    //       let msg = message;
    //       //Print message
    //       console.log(`Hello, ${msg}`);
    //   }
    
  • Question 45

    Private Class Variables

    In ES6, the classes are introduced to create reusable modules and variables are declared in clousure to make them private. Where as in ES2020, private class variables are introduced to allow the variables used in the class only. By just adding a simple hash symbol in front of our variable or function, you can reserve them entirely for internal to the class.

    class User {
    #message = "Welcome to ES2020"
    
    login() { console.log(this.#message) }
    }
    
    const user = new User()
    
    user.login() // Welcome to ES2020
    console.log(user.#message) // Uncaught SyntaxError: Private field '#
    

    Note: As shown in the above code, If you still try to access the variable directly from the object then you will receive syntax error.

    ES2020 Or ES11

    ES2020 is the current newer version of ECMAScript corresponding to the year 2020. This is the eleventh edition of the ECMAScript Language Specification. Even though this release doesn't bring as many features as ES6, it included some really useful features.

    Most of these features already supported by some browsers and try out with babel parser support for unsupported features. This edition is set for final approval by the ECMA general assembly in June, 2020. The ECMAScript 2020 (ES2020) language specification is ready now.

Get LinkedIn Premium at Rs 399