FrontendDeveloper.in

JavaScript Interview Questions

  • Question 406

    What is a Short circuit condition

    Short circuit conditions are meant for condensed way of writing simple if statements. Let's demonstrate the scenario using an example. If you would like to login to a portal with an authentication condition, the expression would be as below,

    if (authenticate) {
    loginToPorta();
    }
    

    Since the javascript logical operators evaluated from left to right, the above expression can be simplified using && logical operator

    authenticate && loginToPorta();
    
  • Question 407

    What is the easiest way to resize an array

    The length property of an array is useful to resize or empty an array quickly. Let's apply length property on number array to resize the number of elements from 5 to 2,

    var array = [1, 2, 3, 4, 5];
    console.log(array.length); // 5
    
    array.length = 2;
    console.log(array.length); // 2
    console.log(array); // [1,2]
    

    and the array can be emptied too

    var array = [1, 2, 3, 4, 5];
    array.length = 0;
    console.log(array.length); // 0
    console.log(array); // []
    
  • Question 408

    What is an observable

    An Observable is basically a function that can return a stream of values either synchronously or asynchronously to an observer over time. The consumer can get the value by calling subscribe() method. Let's look at a simple example of an Observable

    import { Observable } from "rxjs";
    
    const observable = new Observable((observer) => {
    setTimeout(() => {
    observer.next("Message from a Observable!");
    }, 3000);
    });
    
    observable.subscribe((value) => console.log(value));
    

    Screenshot

    Note: Observables are not part of the JavaScript language yet but they are being proposed to be added to the language

  • Question 409

    What is the difference between function and class declarations

    The main difference between function declarations and class declarations is hoisting. The function declarations are hoisted but not class declarations.

    Classes:

    const user = new User(); // ReferenceError
    
    class User {}
    

    Constructor Function:

    const user = new User(); // No error
    
    function User() {}
    
  • Question 410

    What is an async function

    An async function is a function declared with the async keyword which enables asynchronous, promise-based behavior to be written in a cleaner style by avoiding promise chains. These functions can contain zero or more await expressions.

    Let's take a below async function example,

    async function logger() {
    let data = await fetch("http://someapi.com/users"); // pause until fetch returns
    console.log(data);
    }
    logger();
    

    It is basically syntax sugar over ES2015 promises and generators.

  • Question 411

    How do you prevent promises swallowing errors

    While using asynchronous code, JavaScript’s ES6 promises can make your life a lot easier without having callback pyramids and error handling on every second line. But Promises have some pitfalls and the biggest one is swallowing errors by default.

    Let's say you expect to print an error to the console for all the below cases,

    Promise.resolve("promised value").then(function () {
    throw new Error("error");
    });
    
    Promise.reject("error value").catch(function () {
    throw new Error("error");
    });
    
    new Promise(function (resolve, reject) {
    throw new Error("error");
    });
    

    But there are many modern JavaScript environments that won't print any errors. You can fix this problem in different ways,

    1. Add catch block at the end of each chain: You can add catch block to the end of each of your promise chains
    Promise.resolve("promised value")
    .then(function () {
    throw new Error("error");
    })
    .catch(function (error) {
    console.error(error.stack);
    });
    

    But it is quite difficult to type for each promise chain and verbose too.

    1. Add done method: You can replace first solution's then and catch blocks with done method
    Promise.resolve("promised value").done(function () {
    throw new Error("error");
    });
    

    Let's say you want to fetch data using HTTP and later perform processing on the resulting data asynchronously. You can write done block as below,

    getDataFromHttp()
    .then(function (result) {
    return processDataAsync(result);
    })
    .done(function (processed) {
    displayData(processed);
    });
    

    In future, if the processing library API changed to synchronous then you can remove done block as below,

    getDataFromHttp().then(function (result) {
    return displayData(processDataAsync(result));
    });
    

    and then you forgot to add done block to then block leads to silent errors.

    1. Extend ES6 Promises by Bluebird: Bluebird extends the ES6 Promises API to avoid the issue in the second solution. This library has a “default” onRejection handler which will print all errors from rejected Promises to stderr. After installation, you can process unhandled rejections
    Promise.onPossiblyUnhandledRejection(function (error) {
    throw error;
    });
    

    and discard a rejection, just handle it with an empty catch

    Promise.reject("error value").catch(function () {});
    
  • Question 412

    What is deno

    Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 JavaScript engine and the Rust programming language. It solves the inherent problems of Node.Js and has been officially released in May 2018. Unlike Node.JS, by default Deno executes the code in a sandbox, which means that runtime has no access to below areas:

    1. The file system
    2. The network
    3. Execution of other scripts
    4. The environment variables
  • Question 413

    How do you make an object iterable in javascript

    By default, plain objects are not iterable. But you can make the object iterable by defining a Symbol.iterator property on it.

    Let's demonstrate this with an example,

    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}
    

    The above process can be simplified using a generator function,

    const collection = {
    one: 1,
    two: 2,
    three: 3,
    [Symbol.iterator]: function* () {
    for (let key in this) {
    yield this[key];
    }
    },
    };
    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}
    
  • Question 414

    What is a Proper Tail Call

    First, we should know about tail call before talking about "Proper Tail Call". A tail call is a subroutine or function call performed as the final action of a calling function. Whereas Proper tail call(PTC) is a technique where the program or code will not create additional stack frames for a recursion when the function call is a tail call.

    For example, the below classic or head recursion of factorial function relies on stack for each step. Each step need to be processed upto n * factorial(n - 1)

    function factorial(n) {
    if (n === 0) {
    return 1;
    }
    return n * factorial(n - 1);
    }
    console.log(factorial(5)); //120
    

    But if you use Tail recursion functions, they keep passing all the necessary data it needs down the recursion without relying on the stack.

    function factorial(n, acc = 1) {
    if (n === 0) {
    return acc;
    }
    return factorial(n - 1, n * acc);
    }
    console.log(factorial(5)); //120
    

    The above pattern returns the same output as the first one. But the accumulator keeps track of total as an argument without using stack memory on recursive calls.

  • Question 415

    How do you check an object is a promise or not

    If you don't know if a value is a promise or not, wrapping the value as Promise.resolve(value) which returns a promise

    function isPromise(object) {
    if (Promise && Promise.resolve) {
    return Promise.resolve(object) == object;
    } else {
    throw "Promise not supported in your environment";
    }
    }
    
    var i = 1;
    var promise = new Promise(function (resolve, reject) {
    resolve();
    });
    
    console.log(isPromise(i)); // false
    console.log(isPromise(promise)); // true
    

    Another way is to check for .then() handler type

    function isPromise(value) {
    return Boolean(value && typeof value.then === "function");
    }
    var i = 1;
    var promise = new Promise(function (resolve, reject) {
    resolve();
    });
    
    console.log(isPromise(i)); // false
    console.log(isPromise(promise)); // true
    
  • Question 416

    How to detect if a function is called as constructor

    You can use new.target pseudo-property to detect whether a function was called as a constructor(using the new operator) or as a regular function call.

    1. If a constructor or function invoked using the new operator, new.target returns a reference to the constructor or function.
    2. For function calls, new.target is undefined.
    function Myfunc() {
    if (new.target) {
    console.log("called with new");
    } else {
    console.log("not called with new");
    }
    }
    
    new Myfunc(); // called with new
    Myfunc(); // not called with new
    Myfunc.call({}); // not called with new
    
  • Question 417

    What are the differences between arguments object and rest parameter

    There are three main differences between arguments object and rest parameters

    1. The arguments object is an array-like but not an array. Whereas the rest parameters are array instances.
    2. The arguments object does not support methods such as sort, map, forEach, or pop. Whereas these methods can be used in rest parameters.
    3. The rest parameters are only the ones that haven’t been given a separate name, while the arguments object contains all arguments passed to the function
  • Question 419

    What are the different kinds of generators

    There are five kinds of generators,

    1. Generator function declaration:
    function* myGenFunc() {
    yield 1;
    yield 2;
    yield 3;
    }
    const genObj = myGenFunc();
    
    1. Generator function expressions:
    const myGenFunc = function* () {
    yield 1;
    yield 2;
    yield 3;
    };
    const genObj = myGenFunc();
    
    1. Generator method definitions in object literals:
    const myObj = {
    *myGeneratorMethod() {
    yield 1;
    yield 2;
    yield 3;
    },
    };
    const genObj = myObj.myGeneratorMethod();
    
    1. Generator method definitions in class:
    class MyClass {
    *myGeneratorMethod() {
    yield 1;
    yield 2;
    yield 3;
    }
    }
    const myObject = new MyClass();
    const genObj = myObject.myGeneratorMethod();
    
    1. Generator as a computed property:
    const SomeObj = {
    *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
    },
    };
    
    console.log(Array.from(SomeObj)); // [ 1, 2, 3 ]
    
  • Question 420

    What are the built-in iterables

    Below are the list of built-in iterables in javascript,

    1. Arrays and TypedArrays
    2. Strings: Iterate over each character or Unicode code-points
    3. Maps: iterate over its key-value pairs
    4. Sets: iterates over their elements
    5. arguments: An array-like special variable in functions
    6. DOM collection such as NodeList
Get LinkedIn Premium at Rs 399