Pages

Wednesday, February 12, 2025

JavaScript Interview Questions Answers


1. Difference between varlet, and const keywords in JavaScript.

  • 1. var

  • Scope: Function-scoped. A variable declared with var is accessible throughout the function in which it is declared.

  • Hoisting: Variables declared with var are hoisted to the top of their scope and initialized with undefined.

  • Re-declaration: Can be re-declared within the same scope.

  • Use Case: Legacy keyword, generally avoided in modern JavaScript due to its unpredictable behavior.


  • Example:

    javascript
    Copy
    function example() {
      if (true) {
        var x = 10;
      }
      console.log(x); // 10 (accessible outside the block)
    }


    2. let

    • Scope: Block-scoped. A variable declared with let is only accessible within the block (e.g., {}) in which it is defined.

    • Hoisting: Variables declared with let are hoisted but not initialized. Accessing them before declaration results in a ReferenceError (Temporal Dead Zone).

    • Re-declaration: Cannot be re-declared within the same scope.

    • Use Case: Preferred for variables that need to be reassigned.

    Example:

    javascript
    Copy
    function example() {
      if (true) {
        let y = 20;
      }
      console.log(y); // ReferenceError: y is not defined
    }


    3. const

    • Scope: Block-scoped, similar to let.

    • Hoisting: Variables declared with const are hoisted but not initialized. Accessing them before declaration results in a ReferenceError.

    • Re-declaration: Cannot be re-declared or re-assigned. However, for objects and arrays, their properties or elements can be modified.

    • Use Case: Preferred for constants or values that should not be reassigned.

    Example:

    javascript
    Copy
    const z = 30;
    z = 40; // TypeError: Assignment to constant variable.
    
    const obj = { name: "John" };
    obj.name = "Jane"; // Allowed (modifying property)


    Key Differences Summary

    Featurevarletconst
    ScopeFunction-scopedBlock-scopedBlock-scoped
    HoistingHoisted (initialized as undefined)Hoisted (not initialized)Hoisted (not initialized)
    Re-declarationAllowedNot allowedNot allowed
    Re-assignmentAllowedAllowedNot allowed
    Use CaseLegacy codeVariables that changeConstants


    Architectural Implications

    1. Avoid var: In modern JavaScript, var is discouraged due to its function-scoping and hoisting behavior, which can lead to bugs and unpredictable code.

    2. Prefer const: Use const by default for variables that do not need reassignment. This promotes immutability and reduces side effects.

    3. Use let for Mutability: Use let only when reassignment is necessary, such as in loops or dynamic value updates.

    4. Block Scoping: Leverage block scoping (let and const) to limit variable visibility and avoid polluting the global or function scope.


    Example in Practice

    javascript
    Copy
    // Bad: Using var
    var count = 10;
    if (true) {
      var count = 20; // Re-declares the same variable
    }
    console.log(count); // 20 (unexpected behavior)
    
    // Good: Using let and const
    let total = 0;
    const taxRate = 0.1;
    
    for (let i = 0; i < 5; i++) {
      total += i; // Re-assignment allowed with let
    }
    
    console.log(total); // 10
    console.log(taxRate); // 0.1 (constant value)


2. Describe the distinctions between asynchronous and synchronous programming. What pattern does JavaScript follow?

  • Synchronous: Code executes sequentially, blocking further execution until the current operation completes.

  • Asynchronous: Code executes non-blockingly, allowing other operations to run while waiting for the current one to complete.

  • JavaScript Pattern: JavaScript is single-threaded and uses an event-driven, non-blocking I/O model with callbacks, promises, and async/await for asynchronous operations.

  • Example:

    javascript
    Copy
    console.log("Step 1");
    setTimeout(() => console.log("Step 2"), 1000); // Non-blocking
    console.log("Step 3"); // Executes immediately
    1. Use Case:

      • Web servers, APIs, database interactions, and any application involving I/O-bound tasks.


4. What are the fundamental differences between TypeScript and JavaScript?

  • TypeScript: A superset of JavaScript that adds static typing, interfaces, and advanced tooling for better code quality and maintainability.

  • JavaScript: Dynamically typed and more flexible but prone to runtime errors.



5. What are higher-order functions?

  • Definition: Functions that take other functions as arguments or return functions as results.

  • Examplemap()filter(), and reduce().



6. What is the temporal dead zone in JavaScript?

  • Definition: The period between the creation of a variable’s scope and its declaration, where accessing the variable results in a ReferenceError.



7. How to handle multiple asynchronous operations in parallel using promises?

  • Use Promise.all():

    javascript
    Copy
    const [result1, result2] = await Promise.all([promise1, promise2]);



8. Difference between == and ===?

  • ==: Compares values after type coercion.

  • ===: Compares values and types without coercion.



9. Why is it important to use async/await for asynchronous code?

  • Readability: Makes asynchronous code look synchronous and easier to understand.

  • Error Handling: Simplifies error handling with try/catch.



10. Why is JavaScript called a single-threaded language?


  • 1. Core Design Principle

    • JavaScript was designed to run in the browser environment, where it needed to handle user interactions, DOM manipulations, and network requests efficiently.

    • To keep the language simple and avoid complexities like race conditions and deadlocks, JavaScript was implemented as a single-threaded language.

    2. Single Thread of Execution

    • JavaScript has only one call stack, meaning it can execute only one task at a time.

    • This single thread is responsible for executing all JavaScript code, including functions, event handlers, and callbacks.

    3. Event-Driven, Non-Blocking Model

    • Despite being single-threaded, JavaScript can handle asynchronous operations efficiently using the event loop.

    • The event loop allows JavaScript to offload long-running tasks (e.g., I/O operations, timers) to the browser or Node.js runtime and continue executing other tasks without blocking the main thread.

    4. Concurrency Through the Event Loop

    • The event loop continuously checks the call stack and processes tasks from the callback queue or microtask queue.

    • This mechanism enables JavaScript to handle multiple tasks concurrently without requiring multiple threads.


    Implications of Single-Threaded Nature

    1. Advantages

    • Simplicity: Easier to write and reason about code without worrying about thread synchronization or race conditions.

    • Predictability: Single-threaded execution ensures a predictable flow of operations.

    • Efficient for I/O-Bound Tasks: The event-driven model makes JavaScript highly efficient for handling I/O-bound tasks like network requests, file operations, and user interactions.

    2. Challenges

    • CPU-Intensive Tasks: Since JavaScript runs on a single thread, CPU-intensive tasks (e.g., complex calculations, image processing) can block the main thread, making the application unresponsive.

    • Scalability: For CPU-bound workloads, additional techniques like worker threads (in Node.js) or Web Workers (in browsers) are required to achieve parallelism.




    How JavaScript Handles Concurrency

  1. Event Loop:

    • The core of JavaScript's concurrency model.

    • Continuously checks the call stack and processes tasks from the callback queue.

    • Enables non-blocking behavior by deferring long-running tasks and executing them once the call stack is empty.

  2. Callbacks:

    • Functions passed as arguments to asynchronous operations, executed once the operation completes.

    • Example:

      javascript
      Copy
      fs.readFile("file.txt", (err, data) => {
        if (err) throw err;
        console.log(data);
      });
  3. Promises:

    • Represent the eventual completion (or failure) of an asynchronous operation.

    • Provide a cleaner way to handle asynchronous code compared to callbacks.

    • Use .then() for success, .catch() for errors, and .finally() for cleanup. Alternatively, use async/await for cleaner syntax.


    • Example:

      javascript
      Copy
      fetch("https://api.example.com/data")
        .then(response => response.json())
        .then(data => console.log(data))
        .catch(error => console.error(error));
  4. Async/Await:

    • Syntactic sugar built on top of promises.

    • Makes asynchronous code look synchronous, improving readability.

    • Example:

      javascript
      Copy
      async function fetchData() {
        try {
          const response = await fetch("https://api.example.com/data");
          const data = await response.json();
          console.log(data);
        } catch (error) {
          console.error(error);
        }
      }

Example

javascript
Copy
console.log("Start");

setTimeout(() => {
  console.log("Timeout Callback");
}, 1000);

Promise.resolve().then(() => {
  console.log("Promise Callback");
});

console.log("End");

Output:

Copy
Start
End
Promise Callback
Timeout Callback
  • Explanation:

    • Synchronous code (console.log("Start") and console.log("End")) executes first.

    • The Promise callback is a microtask and executes before the setTimeout callback, which is a macrotask.

11. Primitive data types and type coercion in JavaScript.

  • Primitive Typesstringnumberbooleannullundefinedsymbolbigint.

  • Type Coercion: Automatic conversion of values from one type to another (e.g., "5" + 2 results in "52").


12. Difference between for..in and for..of loops.

  • for..in: Iterates over enumerable properties of an object (keys).

  • for..of: Iterates over iterable objects like arrays, strings, etc. (values).



13. Concept of function hoisting and closures.

  • Hoisting: Functions and variables are moved to the top of their scope during compilation.

  • Closures: Functions that retain access to their lexical scope even after the outer function has executed.



14. How to extend a class using ES6 syntax and call the super constructor.

  • Example:

    javascript
    Copy
    class Parent {
      constructor(name) {
        this.name = name;
      }
    }
    class Child extends Parent {
      constructor(name, age) {
        super(name); // Call super constructor
        this.age = age;
      }
    }



15. Importance of this keyword in constructors.

  • this: Refers to the instance of the class being created. Used to assign properties to the object.



16. Difference between null and undefined.

  • null: Represents an intentional absence of value.

  • undefined: Represents an uninitialized or missing value.



17. Why use async/await for asynchronous code?

  • Readability: Makes asynchronous code look synchronous.

  • Error Handling: Simplifies error handling with try/catch.



18. Valid variable names in JavaScript.

  • Rules:

    • Must start with a letter, _, or $.

    • Cannot start with a number.

    • Cannot use reserved keywords.



19. Array methods like splice()push(), and map().

  • splice(): Adds/removes elements from an array.

  • push(): Adds elements to the end of an array.

  • map(): Creates a new array by applying a function to each element.



20. What are closures?

  • Definition: A function that retains access to its lexical scope, even when executed outside that scope.

  • Example:

    javascript
    Copy
    function outer() {
      let count = 0;
      return function inner() {
        count++;
        return count;
      };
    }
    const counter = outer();
    console.log(counter()); // 1


21. Arrow functions in JavaScript.

  • Syntaxconst add = (a, b) => a + b;

  • Features: No this binding, concise syntax.



22. Can functions be assigned to values in JavaScript?

  • Yes: Functions are first-class citizens and can be assigned to variables.

  • Example:

    javascript
    Copy
    const greet = function() {
      console.log('Hello!');
    };





No comments:

Post a Comment