Loading...

Interview Q&A – Crack Your Next Interview

Hoisting is a behavior in JavaScript where variable and function declarations are moved to the top of their containing scope (global or function) during the compilation phase, before code execution.


Example:


var x;         // declaration is hoisted
console.log(x); // undefined
x = 5;         // initialization stays here

  • var: Function-scoped, hoisted, can be re-declared.

  • let: Block-scoped, not hoisted, can be reassigned.

  • const: Block-scoped, not hoisted, cannot be reassigned.

  • Primitive types: String, Number, Boolean, BigInt, Symbol, undefined, null

  • Non-primitive types: Object, Array, Function

It returns the type of a variable:

typeof 'abc'     // "string"
typeof 42        // "number"
typeof {}        // "object"
typeof null      // "object" (legacy bug)

A closure is a function that remembers its outer scope variables even after the outer function has returned.

function outer() {
  let count = 0;
  return function inner() {
    return ++count;
  };
}

const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2

Synchronous

  • Executes line by line, one at a time.

  • Each operation blocks the next one until it completes.

  • Easier to understand but can be slow if a task takes time (e.g., a long loop or API call).

Example:

console.log("1");
console.log("2");
console.log("3");

Asynchronous

  • Allows certain operations to run in the background.

  • Does not block the rest of the code.

  • Useful for tasks like API calls, timers, or reading files.

Example:

console.log("1");
setTimeout(() => {
  console.log("2");
}, 1000);
console.log("3");
Output:
1
3
2

 

A Promise is an object representing the eventual completion (or failure) of an asynchronous operation.
They help you manage asynchronous code (like API calls, file loading, etc.) in a cleaner way than using nested callbacks (callback hell).

A promise has three states:

  1. pending – The initial state (operation still running)

  2. fulfilled – The operation completed successfully

  3. rejected – The operation failed

Example 1:

let checkEven = new Promise((resolve, reject) => {
    let number = 4;
    if (number % 2 === 0) resolve("The number is even!");
    else reject("The number is odd!");
});
checkEven
    .then((message) => console.log(message)) // On success
    .catch((error) => console.error(error)); // On failure

Note: The "resolve" and "reject" are not keywords. You can use any name that you want to give to a function.

Example 2:

let fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Data received!");
  }, 2000);
});
fetchData.then(data => {
  console.log(data); // Data received! after 2 sec
});

Example 3: 

// Create a promise
const myPromise = new Promise((resolve, reject) => {
  const success = true; // Change this to false to simulate rejection
  console.log("Promise is pending...");
  setTimeout(() => {
    if (success) {
      resolve("✅ Promise fulfilled: Data received successfully!");
    } else {
      reject("❌ Promise rejected: Something went wrong!");
    }
  }, 2000); // Simulate an async operation
});
// Handle the promise
myPromise
  .then(result => {
    console.log(result); // Runs if resolved
  })
  .catch(error => {
    console.error(error); // Runs if rejected
  });

async makes a function return a Promise. await pauses the execution until the promise is resolved or rejected.

Example: 

async function fetchData() {
  const result = await fetch('https://api.example.com');
  const data = await result.json();
  return data;
}

Destructuring extracts values from arrays or properties from objects.

1. Array Destructuring

const colors = ['red', 'green', 'blue'];
const [first, second, third] = colors;
console.log(first);  // red
console.log(second); // green
console.log(third);  // blue

2. Object Destructuring

const person = { name: 'John', age: 30 };
const { name, age } = person;
console.log(name); // John
console.log(age);  // 30