JavaScript & React

Secondary priority. These are supporting questions β€” answer confidently on the concept, then connect to backend experience where natural.


JavaScript Fundamentals

1. var vs let vs const

varletconst
ScopeFunctionBlockBlock
HoistingYes (undefined)Yes (TDZ)Yes (TDZ)
ReassignYesYesNo
RedeclareYesNoNo

Always prefer const. Use let when reassignment is needed.


2. == vs ===

== β€” loose equality, performs type coercion (5 == "5" is true).

=== β€” strict equality, checks both value and type (5 === "5" is false).

Always use ===.


3. What is Hoisting?

JavaScript moves variable and function declarations to the top of their scope before execution.

  • var β€” hoisted and initialized as undefined
  • let / const β€” hoisted but remain in the Temporal Dead Zone until the line of declaration

4. What is the Temporal Dead Zone (TDZ)?

The period between entering a scope and initializing a let or const variable. Accessing it before initialization throws ReferenceError.


5. What is a Closure?

A function that retains access to variables from its outer scope even after the outer function has finished executing.

function counter() {
    let count = 0;
    return () => ++count;  // closure over 'count'
}
const inc = counter();
inc(); // 1
inc(); // 2

Uses: data privacy, callbacks, memoization.


6. What is Lexical Scope?

Inner functions can access variables from their outer scope. Scope is determined by where functions are written, not where they’re called.


7. Arrow functions vs Regular functions

ArrowRegular
thisLexical (inherited)Own this
argumentsNoYes
ConstructorNoYes
SyntaxShorterLonger

8. Destructuring

Extract values from arrays or objects.

const { name, age } = user;
const [first, ...rest] = arr;

9. Spread and Rest

Spread (...) β€” expands array/object: const copy = [...arr]

Rest (...) β€” collects remaining values: function sum(...nums) {}


10. Template Literals

Allow embedded expressions using backticks.

`Hello ${name}`

11. Default Parameters

Assign default values if arguments are omitted.

function greet(name = "Guest") { ... }

12. Optional Chaining and Nullish Coalescing

user?.address?.city     // safely access nested β€” returns undefined if any is null
name ?? "Guest"         // returns right side only if left is null or undefined

Async JavaScript

13. What is a Callback?

A function passed to another function and executed later. Can lead to β€œcallback hell” β€” deeply nested code.


14. Callback Hell

Deeply nested callbacks that reduce readability. Solved using Promises or async/await.


15. What is a Promise?

Represents the eventual completion or failure of an async operation.

States: Pending β†’ Fulfilled or Rejected

Methods: .then() Β· .catch() Β· .finally()


16. Promise Methods (Static)

  • Promise.all() β€” waits for all to fulfill, or fails if any fails.
  • Promise.allSettled() β€” waits for all to finish, regardless of success.
  • Promise.race() β€” resolves/rejects as soon as the first promise finishes.
  • Promise.any() β€” resolves as soon as any promise fulfills.

17. async/await

Syntactic sugar over Promises. Makes async code look synchronous while remaining non-blocking.

async function fetchUser(id) {
    const user = await db.query(id);  // pauses here, doesn't block
    return user;
}

18. async vs Promise

async functions implicitly return a Promise. await is used to pause execution until a Promise resolves. They are functionally equivalent to .then() chains but more readable.


19. What is the Event Loop?

JavaScript is single-threaded. The Event Loop continuously checks:

  1. Call Stack β€” currently executing code
  2. Microtask Queue β€” Promise callbacks (higher priority)
  3. Callback Queue β€” setTimeout, DOM events

Microtasks run before the next callback queue item.


20. Call Stack

A LIFO (Last In, First Out) stack that stores currently executing function calls.


21. Microtask Queue

A higher-priority queue executed before the callback queue. Contains Promise callbacks and queueMicrotask().


22. Callback Queue (Macrotask Queue)

Stores asynchronous callbacks from setTimeout, DOM events, and I/O.


23. setTimeout(fn, 0) β€” when does it run?

Not immediately. The callback is placed in the Callback Queue and only runs after the current call stack is empty and all microtasks complete.


24. Array methods

MethodReturnsUse
map()New array (same length)Transform each element
filter()New array (shorter)Keep matching elements
reduce()Single valueAggregate
forEach()undefinedSide effects only
find()First matchSingle element search

25. find() vs filter()

find() returns the first matching element (or undefined). filter() returns a new array of all matching elements (or an empty array).


26. Object.keys(), Object.values(), Object.entries()

  • Object.keys() β€” Returns an array of keys.
  • Object.values() β€” Returns an array of values.
  • Object.entries() β€” Returns an array of [key, value] pairs.

27. Deep Copy vs Shallow Copy

Shallow β€” Object.assign({}, obj) or {...obj}. Nested objects are still shared references.

Deep β€” JSON.parse(JSON.stringify(obj)) (simple), or structuredClone() (modern).


React

28. What is React?

JavaScript library for building reusable component-based user interfaces. Uses a declarative approach β€” describe what the UI should look like, React handles updates.


29. What is JSX?

A syntax extension allowing HTML-like code inside JavaScript. React compiles it down to React.createElement() calls.


30. What is a Component?

A reusable piece of UI that accepts inputs (props) and manages its own state.


31. Functional Component vs Class Component

Functional components use Hooks and are the modern standard.

Class components use lifecycle methods (componentDidMount, etc.) and are now less common.


32. Props vs State

Props β€” passed from parent, read-only inside the component.

State β€” managed within the component, can change over time and triggers re-renders.


33. useState()

Hook for managing component state.

const [count, setCount] = useState(0);

34. useEffect()

Runs side effects after render: API calls, timers, subscriptions.

useEffect(() => {
    fetchData();
    return () => cleanup();  // cleanup on unmount
}, [dependency]);            // runs when 'dependency' changes

Dependency array:

  • [] β€” runs once on mount
  • [val] β€” runs when val changes
  • Omitted β€” runs after every render

35. useMemo() vs useCallback()

useMemo() β€” memoizes a computed value. Avoids expensive recalculation.

useCallback() β€” memoizes a function reference. Avoids recreating functions on every render.

const expensiveValue = useMemo(() => compute(data), [data]);
const handleClick = useCallback(() => doSomething(id), [id]);

36. useMemo vs useCallback

useMemo memoizes the result of a function call. useCallback memoizes the function reference itself.


37. What is the Virtual DOM?

An in-memory representation of the real DOM. React compares the new Virtual DOM with the previous version (diffing/reconciliation) and applies only the minimal set of changes to the real DOM. Improves rendering performance.


38. Controlled vs Uncontrolled Components

Controlled β€” form element value managed by React state. Single source of truth.

Uncontrolled β€” form element manages its own state. Access via ref.


39. Context API

Shares state across components without prop drilling. Useful for themes, auth, language settings.

const ThemeContext = React.createContext('light');
// Provider wraps the tree, Consumer/useContext reads the value

40. What is Prop Drilling?

Passing props through multiple intermediate components just to reach a deeply nested child. Solved with Context API or state management (Zustand, Redux).


41. React Keys

Unique identifiers used by React to track list items during reconciliation. Helps React know which items were added, removed, or reordered.

Use stable, unique IDs β€” not array indices.


42. React Fragment

Groups multiple elements without adding an extra node to the DOM (<React.Fragment> or <>...</>).


43. React component lifecycle (functional)

  • Mount β€” useEffect(() => {}, [])
  • Update β€” useEffect(() => {}, [dep])
  • Unmount β€” cleanup function returned from useEffect

TypeScript

44. Why TypeScript?

Adds static typing to JavaScript. Catches type errors at compile time, improves IDE support and code maintainability.


45. Interface vs Type

Interface β€” best for object shapes. Can be extended and merged.

Type β€” more flexible. Supports unions, intersections, tuples, primitives.

interface User { name: string; age: number }
type ID = string | number;

46. Generics

Write reusable, type-safe code without sacrificing flexibility.

function identity<T>(value: T): T { return value; }
identity<string>("hello");
identity<number>(42);

47. Union Types

A variable that can hold one of several types.

type Result = string | number | null;

48. Optional Properties and Optional Chaining

interface User { name: string; age?: number }  // age is optional
const age = user?.age;  // safe access

49. any vs unknown

any β€” disables type checking. Avoid.

unknown β€” type-safe alternative. Must check type before using.

function parse(input: unknown) {
    if (typeof input === "string") return input.toUpperCase();
}

50. Type Narrowing

Refining a broad type to a specific one using checks: typeof, instanceof, or type guards.


51. Enums

Named set of constant values.

enum Status { Pending, Approved, Rejected }
const s: Status = Status.Approved;

52. Strict Mode

TypeScript compiler option ("strict": true) that enables rigorous type checking β€” catches more errors at compile time.


53. Type Assertion

Tells TypeScript to treat a value as a specific type, overriding the compiler’s inference.

const input = document.getElementById("id") as HTMLInputElement;