FrontendDeveloper.in

ECMAScript Interview Questions

  • Question 1

    Variable Scoping

    The variable scoping determines the visibility or accessibility of a variable within the certain part of the program or region.

    In ES6, both const and let keywords allow developers to declare variables in the block scope.

    The let statement declares a block-scoped local variable which can be reassigned. i.e, let declaration creates a mutable variable.

    let a = 1;
    
    if (a === 1) {
    let a = 2;
    
    console.log(a); //2
    }
    
    console.log(a); //1
    

    const variables are similar to let variables but they can't be changed through reassignment. i.e, The const declaration creates a read-only reference to a value.

    const x = 1;
    
    if (x === 1) {
    const y = 2; // You cannot re-assign the value similar to let variable
    
    console.log(y); //2
    }
    
    console.log(x); //1
    
  • Question 2

    Arrow functions

    The arrow functions provides a more concise syntax for writing function expressions by opting out the function and return keywords using fat arrow(=>) notation. Let's see how this arrow function looks like,

    // Function Expression
    var multiplyFunc = function(a, b) {
    return a * b;
    }
    console.log(multiplyFunc(2, 5)); // 10
    
    // Arrow function
    var multiplyArrowFunc = (a, b) => a * b;
    console.log(multiplyArrowFunc(2, 5)); // 10
    

    You can also skip parenthesis(()) if the function has exactly one parameter(either zero or more than one parameter). Apart from this, you can wrap braces({}) if the function has more than one expression in the body.

    Let's list down all the variations of arrow functions,

    //1. Single parameter and single statement
    const message = name => console.log("Hello, " + name + "!");
    message("Sudheer"); // Hello, Sudheer!
    
    //2. Multiple parameters and single statement
    const multiply = (x, y) => x * y;
    console.log(multiply(2, 5)); // 10
    
    //3. Single parameter and multiple statements
    const even = number => {
    if(number%2) {
    console.log("Even");
    } else {
    console.log("Odd");
    }
    }
    even(5); // odd
    
    //4. Multiple parameters and multiple statements
    const divide = (x, y) => {
    if(y != 0) {
    return x / y;
    }
    }
    console.log(divide(100, 5)); // 20
    
    //5. No parameter and single statement
    const greet = () => console.log('Hello World!');
    greet(); // Hello World!
    
  • Question 3

    Classes

    The classes are introduced as syntactic sugar over existing prototype based inheritance and constructor functions. So this feature doesn't bring new object-oriented inheritance model to JavaScript.

    There are two ways to define classes,

    1. Class declarations:
    class Square {
    constructor(length) {
    this.length = length;
    }
    
    get area() {
    return this.length * this.length;
    }
    
    set length(value) {
    this.length = value;
    }
    }
    
    1. Class expressions:
    const square = class Square {
    constructor(length) {
    this.length = length;
    }
    
    get area() {
    return this.length * this.length;
    }
    
    set length(value) {
    this.length = value;
    }
    }
    

    You can use extend keyword to use inheritance. This enables the subclass to get all features of a parent class.

    class Vehicle {
    constructor(name) {
    this.name = name;
    }
    
    start() {
    console.log(`${this.name} vehicle started`);
    }
    }
    
    class Car extends Vehicle {
    start() {
    console.log(`${this.name} car started`);
    }
    }
    
    const car = new Car('BMW');
    console.log(car.start()); // BMW car started
    

    Note: Even though ES6 classes looks similar to classes in other object oriented languages, such as Java, PHP, etc but they do not work exactly the same way.

  • Question 4

    Enhanced object literals

    Object literals are extended to support setting the prototype at construction, shorthand for foo: foo assignments, defining methods, making super calls, and computing property names with expressions.

    The important enhancements of object literals are,

    1. Property Shorthand:

    Object's properties are often created from variables with the same name.

    Let's see the ES5 representation

    var a = 1, b = 2, c = 3,
    obj = {
    a: a,
    b: b,
    c: c
    };
    console.log(obj);
    

    and it can be represented in a shorter syntax as below,

    const a = 1, b = 2, c = 3;
    const obj = {
    a,
    b,
    c
    };
    console.log(obj);
    
    1. Method Shorthand: In ES5, Object methods require the function statement as below,
    var calculation = {
    sum: function(a, b) { return a + b; },
    multiply: function(a, b) { return a * b; }
    };
    
    console.log(calculation.sum(5, 3));  // 8
    console.log(calculation.multiply(5, 3)); // 15
    

    This can be avoided in ES6,

    const calculation = {
    sum(a, b) { return a + b; },
    multiply(a, b) { return a * b; }
    };
    
    console.log(calculation.sum(5, 3));  // 8
    console.log(calculation.multiply(5, 3)); // 15
    
    1. Computed Property Names: In ES5, it wasn’t possible to use a variable for a key name during object creation stage.
    var
    key = 'three',
    obj = {
    one: 1,
    two: 2
    };
    
    obj[key] = 3;
    

    Object keys can be dynamically assigned in ES6 by placing an expression in square brackets([])

    const
    key = 'three',
    computedObj = {
    one: 1,
    two: 2,
    [key]: 3
    };
    
  • Question 5

    Template literals

    Prior to ES6, JavaScript developers would need to do ugly string concatenation to creat dynamic strings.

    Template literals allows you to work with strings in a new way compared to ES5. These are just string literals allowing embedded expressions denoted by the dollar sign and curly braces (${expression}). Also, these literals are enclosed by the backtick (`) character instead of double or single quotes.

    ES6 has two new kinds of literals:

    1. Template literals: string literals which exists across multiple lines and include interpolated expressions(i.e, ${expression})
    const firstName = 'John';
    console.log(`Hello ${firstName}!
    Good morning!`);
    
    1. Tagged template literals: Function calls which are created by mentioning a function before a template literal.

    The real world use case is creating components in CSS-In-JS styled components to use across the application

    const Button = styled.a`
    display: inline-block;
    border-radius: 3px;
    `
    
  • Question 6

    Destructuring

    Destructuring is a javascript expression for extracting multiple values from data stored in objects(properties of an object) and Arrays.

    Object destructuring:

    This feature is used to extract values from an object.

    const user = { firstName: 'John', lastName: 'Kary' };
    const {firstName, lastName} = user;
    console.log(firstName, lastName); // John, Kary
    

    Array destructuring:

    This feature is used to extract values from an array.

    const [one, two, three] = ['one', 'two', 'three'];
    console.log(one, two, three); // one, two, three
    

    You can use destructing in below places,

    1. Variable declarations
    2. Assignments
    3. Parameter definitions
    4. for-of loop
  • Question 7

    Default parameters

    Default parameters allow named parameters of a function to be initialized with default values if no value or undefined is passed.

    Prior to ES6, you need check for undefined values and provide the default value for undefined values using if/else or ternary operator

    function add(a, b) {
    a = (typeof a !== 'undefined') ? a : 10;
    b = (typeof b !== 'undefined') ? b : 20;
    return a + b;
    }
    add(20); // 40
    add(); // 30
    

    In ES6, these checks can be avoided using default parameters

    function add(a = 10, b = 20) {
    return a + b;
    }
    add(20); // 40
    add(); // 30
    
  • Question 8

    Rest parameter

    The rest parameter is used to represent an indefinite number of arguments as an array. The important point here is only the function's last parameter can be a "rest parameter". This feature has been introduced to reduce the boilerplate code that was induced by the arguments.

    function sum(...args) {
    return args.reduce((previous, current) => {
    return previous + current;
    });
    }
    
    console.log(sum(1, 2, 3)); // 6
    console.log(sum(1, 2, 3, 4)); // 10
    console.log(sum(1, 2, 3, 4, 5)); // 15
    
  • Question 9

    Spread Operator

    Spread Operator allows iterables( arrays / objects / strings ) to be expanded into single arguments/elements.

    1. In function and constructor calls, the spread operator turns iterable values into arguments
    console.log(Math.max(...[-10, 30, 10, 20])); //30
    console.log(Math.max(-10, ...[-50, 10], 30)); //30
    
    1. In Array literals and strings, the spread operator turns iterable values into Array elements
    console.log([1, ...[2,3], 4, ...[5, 6, 7]]); // 1, 2, 3, 4, 5, 6, 7
    

    Note: The spread syntax is opposite of rest parameter.

  • Question 10

    Iterators & For..of

    String, Array, TypedArray, Map, and Set are all built-in iterables but objects are not iterables by default. Iterators are a new way to loop over any collection in JavaScript. These are objects which defines a sequence and potentially a return value upon its termination. An iterator implements the Iterator protocol by having a next() method that returns an object with two properties:

    1. value: The next value in the iteration sequence.
    2. done: returns true if the last value in the sequence has already been consumed.

    You can make the object iterable by defining a Symbol.iterator property on it.

    const collection = {
    one: 1,
    two: 2,
    three: 3,
    [Symbol.iterator]() {
    const values = Object.keys(this);
    let i = 0;
    return {
    next: () => {
    return {
    value: this[values[i++]],
    done: i > values.length
    }
    }
    };
    }
    };
    
    const iterator = collection[Symbol.iterator]();
    
    console.log(iterator.next());    // → {value: 1, done: false}
    console.log(iterator.next());    // → {value: 2, done: false}
    console.log(iterator.next());    // → {value: 3, done: false}
    console.log(iterator.next());    // → {value: undefined, done: true}
    
    for (const value of collection) {
    console.log(value);
    }
    

    The for...of statement creates a loop iterating over user defined collection object. But this loop can be used for built-in objects too.

    Note: The abrupt iteration termination can be caused by break, throw or return.

  • Question 11

    Generators

    A generator is a function that can stop or suspend midway and then continue from where it stopped while maintaining the context(saved across re-entrances). It can be defined using a function keyword followed by an asterisk(i.e, function* ()).

    This function returns an iterator object and this iterator's next() method returns an object with a value property containing the yielded value and a done property which indicates whether the generator has yielded its last value.

    function* myGenerator(i) {
    yield i + 10;
    yield i + 20;
    return i + 30;
    }
    
    const myGenObj = myGenerator(10);
    
    console.log(myGenObj.next().value); // 20
    console.log(myGenObj.next().value); // 30
    console.log(myGenObj.next().value); // 40
    

    Note: We can use yield* to delegate to another generator function

  • Question 12

    Modules

    Modules are small units of independent, reusable code to be used as the building blocks in a Javascript application.

    Prior to ES6, there was no native modules support in JavaScript. There were 3 major module standards used,

    1. Asynchronous Module Definition (AMD)
    2. RequireJS Modules
    3. CommonJS Modules (module.exports and require syntax used in Node.js)

    ES6 has provided the built-in support for modules. Everything inside a module is private by default, and runs in strict mode. Public variables, functions and classes are exposed using export statement and import the same using import statement.

    Export Statement:

    There are two types of exports:

    1. Named Exports (Zero or more exports per module)

    You can export each element or a single export statement to export all the elements at once

    // module "my-module.js"
    
    const PI = Math.PI;
    
    function add(...args) {
    return args.reduce((num, tot) => tot + num);
    }
    
    function multiply(...args) {
    return args.reduce((num, tot) => tot * num);
    }
    
    // private function
    function print(msg) {
    console.log(msg);
    }
    
    export { PI, add, multiply };
    
    1. Default Exports (One per module)

    If we want to export a single value, you could use a default export

    // module "my-module.js"
    
    export default function add(...args) {
    return args.reduce((num, tot) => tot + num);
    }
    

    Import Statement:

    The static import statement is used to import read only live bindings which are exported by another module.

    There are many variations of import scenarios as below,

    // 1. Import an entire module's contents
    import * as name from "my-module";
    
    //2.Import a single export from a module
    import { export1 } from "my-module";
    
    //3.Import multiple exports from a module
    import { export1 , export2 } from "my-module";
    
    //4.Import default export from a module
    import defaultExport from "my-module";
    
    //5.Import an export with an alias
    import { export1 as alias1 } from "my-module";
    
    
  • Question 13

    Set

    Set is a built-in object to store collections of unique values of any type.

    let mySet = new Set()
    
    mySet.add(1);
    mySet.add(2);
    mySet.add(2);
    mySet.add('some text here');
    mySet.add({one: 1, two: 2 , three: 3});
    console.log(mySet); // Set [ 1, 2, 'some text here', {one: 1, two: 2 , three: 3} ]
    console.log(mySet.size) // 4
    console.log(mySet.has(2)); // true
    
  • Question 14

    Weakset

    The Set is used to store any type of data such as primitives and object types. Whereas WeakSet is an object to store weakly held objects in a collection. (i.e, WeakSet is the collections of objects only). Here weak means, If no other references to an object stored in the WeakSet exist, those objects can be garbage collected.

    let myUserSet = new WeakSet();
    
    let john = { name: "John" };
    let rocky = { name: "Rocky" };
    let alex = { name: "Alex" };
    let nick = { name: "Nick" };
    
    myUserSet.add(john);
    myUserSet.add(rocky);
    myUserSet.add(john);
    myUserSet.add(nick);
    
    console.log(myUserSet.has(john)); // true
    console.log(myUserSet.has(alex)); // false
    console.log(myUserSet.delete(nick));
    console.log(myUserSet.has(nick)); // false
    
    john = null;
    
  • Question 15

    Map

    Map is a collection of elements where each element is stored as a Key, value pair. It can hold both objects and primitive values as either key or value and iterates its elements in insertion order.

    Let's take a map with different types of primitives and objects as key-value pairs and various methods on it,

    let typeMap = new Map();
    
    var keyObj = {'one': 1}
    
    typeMap.set('10', 'string');   // a string key
    typeMap.set(10, 'number');     // a numeric key
    typeMap.set(true, 'boolean');  // a boolean key
    typeMap.set(keyObj, 'object'); // an object key
    
    console.log(typeMap.get(10));         // number
    console.log(typeMap.get('10'));       // string
    console.log(typeMap.get(keyObj));     // object
    console.log(typeMap.get({'one': 1})); // undefined
    
    console.log(typeMap.size ); // 4
    
    for(let item of typeMap) {
    console.log(item);
    }
    
    for(let item in typeMap) {
    console.log(item);
    }
    
Get LinkedIn Premium at Rs 399