Frontend Developer Interview Question

Top Interview Questions for Aspiring Developers

  1. How does callback hell happen? How to avoid it?

    - Asynchronous operations are triggered: In an asynchronous environment, code can trigger multiple operations that happen concurrently. For example, you might need to read a file from disk, fetch data from a remote server, and process some data, all at the same time.
    - Callbacks are nested: When one asynchronous operation depends on the result of another operation, the callback for the first operation is nested within the callback for the second operation. This nesting can continue for multiple operations, resulting in deeply nested callbacks.
    - Code becomes hard to read and maintain: As the number of nested callbacks increases, the code becomes harder to read and maintain. It can become challenging to keep track of the order in which the callbacks will execute, and it can be difficult to understand the flow of the code.
    How to avoid callback hell?
    - Use Promises: Promises are a way to handle asynchronous operations in JavaScript. They provide a cleaner and more organized way of handling asynchronous code than callbacks.
    - Use async/await: async/await is a new way of writing asynchronous code in JavaScript that was introduced in ES2017. It allows you to write asynchronous code in a synchronous way, making it easier to read and understand.
    - Use error handling: Handle errors in a consistent and organized way to avoid confusion and ensure that the code is stable.
    2 Things to keep in mind while doing so:
    - Use try/catch: When using async/await, errors can be caught using a try/catch block. This makes error handling more readable and easier to understand. Always use try/catch to catch and handle errors.
    - Use async function: To use the await keyword, the function must be marked as async. This means that the function will always return a Promise. If you don't mark the function as async, you won't be able to use the await keyword.

  2. Difference between async await and promise.

    Intro line
    - Promises and async/await are both used to manage asynchronous operations in JavaScript. Promises are a way to handle asynchronous operations in a more readable and manageable way, while async/await is a syntactic sugar over Promises that makes asynchronous code look more like synchronous code.

    3 points compared & contrasted
    - Syntax: Promises use a then() method to handle the results of asynchronous operations, while async/await uses the async keyword to mark a function as asynchronous and the await keyword to wait for the result of an asynchronous operation.
    - Error handling: With Promises, you can use the catch() method to handle errors, while with async/await, you can use a try/catch block to catch errors.
    - Chaining: With Promises, you can chain multiple asynchronous operations together using the then() method. With async/await, you can use the await keyword to wait for the result of an asynchronous operation before moving on to the next one.

  3. Local storage vs session storage vs cookies

    Intro line:
    - All three browser storage mechanisms - localStorage, sessionStorage, and cookies - serve the common purpose of allowing web applications to store data in a user's browser.
    3 points of comparison:
    Storage duration:
    - localStorage: stores data with no expiration date.
    - sessionStorage: stores data for one session, which is terminated when the browser is closed.
    - cookies: can have an expiration date or be stored permanently.
    Storage limit:
    - localStorage: limited to 5-10MB of data, depending on the browser.
    - sessionStorage: limited to 5-10MB of data, depending on the browser.
    - cookies: limited to 4KB of data per cookie, and most browsers limit the total number of cookies a site can set.
    Main use cases:
    - localStorage: storing user preferences, and shopping cart items.
    - sessionStorage: temporary preferences and form data.
    - cookies: login information, tracking user activity, or personalizing content.

  4. Throttling vs Debouncing
    Intro line:
    - Throttling and debouncing are techniques used to control the frequency of a function’s execution in response to frequent events resulting in performance optimization and preventing unnecessary or duplicate function calls.
    3 points of comparison:
    Rate of Execution: 
    - Throttling limits the rate at which a function can be called over a specified period.
    - Debouncing delays the execution of a function until a specified amount of time has passed without the event being triggered again.
    Use case:
    - Throttling can be used to regulate the frequency of certain tasks that are resource-intensive or repetitive.
    - Debouncing is useful when an event may trigger multiple times in quick succession, such as keyboard input or scrolling.
    Usage:
    - Throttling ensures that the function is executed at a set interval, allowing for more efficient resource utilization.
    - Debouncing guarantees that the function will only be executed once after a series of events, improving performance and reducing resource usage.

  5. Difference between == and ===
    Intro line
    - The equality operator in javascript is used to compare if two values are equal. The comparison is made by == and === operators in javascript.
    3 points compared & contrasted
    Return value: 
    -> The == returns true if operands have same value, returns false if the values differ.
    -> The === returns true only if operands are of same data type and same value, otherwise returns false
    Coercion:
    - In case both operands are of different data types, == performs type conversion of one operand in order to make the data types of the operands the same.
    - In case both operands are of different data type, === doesn't perform type conversion of the operands.
    Named as:
    \== is known as loose equality.
    \=== is known as strict equality.

  6. What is reconciliation in React?
    Need:
    Reconciliation optimizes UI updates, minimizing DOM manipulation, developers would face manual, error-prone updates and poor performance due to excessive DOM changes.
    What is it:
    - A process to update UI efficiently

    - Compares current and new virtual DOMs

    - Calculates differences ("diff") between trees

    - Applies minimal DOM changes based on differences

    - Supports React's declarative programming style

    - Improves user experience and performance
    How it is used:
    - Reconciliation is an integral part of react that works automatically triggers UI updates when there is a state or prop change.

  7. What is Array.reduce?
    Need of it:
    ->Array.reduce is needed in JavaScript to perform data manipulation on array objects in a more efficient and concise manner than traditional looping methods.
    What it is:
    - Array.reduce is a built-in method in JavaScript that applies a function to each element of an array to reduce it to a single value.

    - The method takes two parameters: a callback function and an optional initial value.

    - The callback function takes two arguments: an accumulator and the current value and returns the new value of the accumulator.

    - The reduce method returns the final value of the accumulator.
    How to use:
    - Define a callback function that takes an accumulator and a current value, performs some operation on them, and returns the new value of the accumulator.

    - Call the reduce method on an array, passing in the callback function and an optional initial value as parameters.

    - The reduce method applies the callback function to each element of the array, updating the accumulator at each step and returning the final value.

  8. What is prop drilling?
    Need of it:
    Prop drilling in React is needed to pass data down the component tree when it is needed by child components that are several levels deep.
    What it is:
    Prop drilling is a technique in React where data is passed down through multiple levels of nested components via props.
    How to use:
    - Pass data down through props from the parent component to the child component that needs it.

    - If the data is needed by a grandchild or great-grandchild component, pass it down through intermediate components using props as well.

    - Be careful not to overuse prop drilling, as it can make the code harder to maintain and lead to performance issues.

    - Consider using the Context API or a state management library like Redux to avoid prop drilling and manage shared data more efficiently.

  9. What is memoization?
    Need:
    - Avoid recomputing output of time-consuming functions which returns the same value when called multiple times with the same set of inputs
    What is it:
    - Memoization is a performance optimization technique that involves caching the results of expensive function calls first time its called with a specific input and reusing the output when the function is called subsequently with the same set of input .
    How to use it:
    - In JS: we can either use a library like lodash or write our own implementation using an object to store the cached values

    - In React, use React.memo(): Wrap a function component with React.memo() to memoize it and only re-render it when its props have changed.

    - In React, useMemo(): Use the useMemo() hook to memoize the result of a function call and only recompute it when the dependencies of that function change