JavaScript

JavaScript interview QBank (concise, technical, “why/how”).


1) What are the primitive types in JavaScript, and why do they matter?

Answer: Primitives are string, number, bigint, boolean, undefined, symbol, null . They’re immutable and passed by value (the value is copied). This impacts comparisons, object keys, and behavior like typeof.


2) Why is typeof null equal to "object"?

Answer: It’s a legacy bug from early JS implementations. null is a primitive, but typeof null returns "object" for backward compatibility.


3) What’s the difference between undefined and null?

Answer: undefined usually means “ not assigned / missing ” (default for uninitialized variables, missing properties). null is an intentional empty value set by the developer.


4) How does JavaScript handle numbers internally?

Answer: number is typically IEEE-754 double precision float . That’s why decimal math can be imprecise (0.1 + 0.2 !== 0.3) and why large integers may need bigint.


5) When should you use BigInt?

Answer: Use BigInt for integers beyond Number.MAX_SAFE_INTEGER (~9e15) when exactness matters (IDs, cryptography-like arithmetic, counters). You can’t mix BigInt and Number without explicit conversion.


6) Explain pass-by-value vs pass-by-reference in JS.

Answer: JS is pass-by-value always. For objects, the “value” is a reference (pointer) to the object, so passing an object copies the reference—mutations affect the same underlying object.


7) Why do objects compare differently than primitives?

Answer: Objects compare by reference identity , not structure. Two identical object literals are different references.


8) What is type coercion, and why is it dangerous?

Answer: Type coercion is JS converting types implicitly (e.g., during +, ==, comparisons). It’s dangerous because it can produce surprising results and hide bugs.


9) Explain == vs === with a real “why”.

Answer: == allows coercion (tries to make types comparable). === is strict (no coercion), so it’s more predictable and safer for most codebases.


10) Why is 0 == false true but 0 === false false?

Answer: == coerces false to 0, so 0 == 0. === checks both type and value: number vs boolean => false.


11) What are the falsy values in JS, and how does that affect logic?

Answer: Falsy: false, 0, -0, 0n, "", null, undefined, NaN. In conditionals, these behave as false, which can break logic if you treat 0 as “missing”.


12) What’s the difference between || and ???

Answer: || returns the right side when left is falsy ; ?? returns the right side only when left is null or undefined . ?? is safer for values like 0 or "".


13) What is hoisting, and what exactly gets hoisted?

Answer: Hoisting is compile-time behavior where declarations are processed before execution.

  • var is hoisted and initialized to undefined

  • let/const are hoisted but in TDZ (not usable before declaration)

  • function declarations are hoisted with implementation


14) Why does var behave differently than let/const?

Answer: var is function-scoped and permits redeclaration, often causing bugs. let/const are block-scoped and safer in loops and closures.


15) Explain TDZ (Temporal Dead Zone) in simple technical terms.

Answer: TDZ is the period from entering the scope until the let/const declaration executes. Accessing the variable in that window throws ReferenceError, preventing use-before-declare bugs.


16) What happens in this code and why?

Answer: Logs undefined because var a is hoisted and initialized to undefined, then assignment happens later.


17) What happens here and why?

Answer: Throws ReferenceError due to TDZ. a exists in the scope but isn’t initialized until the declaration runs.


18) What’s the difference between function declaration and function expression hoisting?

Answer: Function declarations are hoisted fully (callable before definition). Function expressions assigned to var/let/const depend on variable hoisting rules; only the variable is hoisted, not the function body.


19) Why does this work?

Answer: Function declaration is hoisted with its body, so foo is callable before the line appears.


20) Why does this fail?

Answer: foo is in TDZ until const is initialized.


21) Explain lexical scope (“how it works”).

Answer: Lexical scope means scope is determined by where code is written , not where it’s called. Inner functions keep access to variables from their defining environment.


22) What is block scope, and when does it matter most?

Answer: Block scope means { ... } creates a scope for let/const. It matters in loops and conditionals to avoid leaking variables and closure bugs.


23) Why does let fix the classic loop + closure bug?

Answer: let creates a new binding per iteration in for loops, so each closure captures the correct value.


24) Compare var, let, const in 3 interview points.

Answer:

  • Scope: var function-scoped; let/const block-scoped

  • Hoisting: var initialized to undefined; let/const TDZ

  • Reassign: var/let reassignable; const not reassignable (but object contents can mutate)


25) Why can you mutate a const object?

Answer: const prevents reassigning the variable binding , not mutating the object it references.


26) What is the global object and why does it differ (browser vs Node)?

Answer: Browser global object is window (or globalThis); Node uses global. Differences affect top-level this, globals, and environment APIs.


27) Why is globalThis useful?

Answer: It’s a standard cross-platform way to access the global object (works in browser, Node, workers).


28) How does this behave at the top level?

Answer: In browsers (non-module), top-level this === window. In ES modules, top-level this is undefined. In Node, top-level this is module-scoped (not global).


29) What’s the difference between NaN and “not defined”?

Answer: NaN is a number value meaning “invalid number result”. “Not defined” refers to an undeclared identifier -> ReferenceError.


30) Why does Number.isNaN() exist when isNaN() already exists?

Answer: isNaN() coerces first (so "x" becomes NaN -> true). Number.isNaN() is strict: only true if the value is actually NaN.


31) What’s the difference between parseInt("08") and Number("08")?

Answer: parseInt parses until invalid char and can take radix; Number converts the entire string. parseInt("08") -> 8, but always prefer specifying radix: parseInt(s, 10).


32) Explain the difference between + unary and Number().

Answer: Both coerce to number, but unary + is shorter and common in hot paths. Both can produce NaN. Prefer readability: Number(x).


33) What happens with + when one operand is a string?

Answer: + becomes string concatenation if either operand is a string (after coercion). That’s why 1 + "2" === "12".


34) Why does [] + [] produce an empty string?

Answer: + triggers primitive conversion. Arrays become "" via .toString(), so "" + "" => "".


35) Why is [] == false true?

Answer: == coercion: [] -> "" -> 0; false -> 0. So 0 == 0 => true. This is why strict equality is recommended.


36) Explain Object.is() vs ===.

Answer: Object.is() is like === but treats NaN as equal to itself and distinguishes +0 and -0.


37) What is a “reference error” vs “type error”?

Answer: ReferenceError: variable not declared / TDZ access. TypeError: value exists but used incorrectly (calling non-function, accessing property on null/undefined).


38) What is a “shallow copy” and why does it bite?

Answer: Shallow copy copies only the top-level references. Nested objects remain shared, so mutations leak.


39) How does typeof behave for common values?

Answer:

  • typeof "x" -> "string"

  • typeof 1 -> "number"

  • typeof undefined -> "undefined"

  • typeof null -> "object" (bug)

  • typeof [] -> "object"

  • typeof (()=>{}) -> "function"


40) How do you reliably check for arrays?

Answer: Use Array.isArray(x) because typeof [] is "object" and instanceof Array can fail across realms/iframes.


41) Why does delete behave differently on variables vs object properties?

Answer: delete removes object properties , not local variables. Variables declared with let/const/var aren’t deletable in that way.


42) What is the difference between in and hasOwnProperty?

Answer: in checks property in the object or its prototype chain . hasOwnProperty checks only own properties .


43) What are “own properties” vs inherited properties?

Answer: Own properties exist directly on the object. Inherited ones come from the prototype chain. This matters for iteration and security (for...in includes inherited).


44) Why is for...in risky on objects?

Answer: It iterates enumerable properties including inherited ones. Prefer Object.keys(), Object.entries(), or Object.hasOwn() checks.


45) What does “immutability” mean for primitives?

Answer: You can’t change a primitive in-place. Operations create a new value. Example: "a".toUpperCase() returns new string; original is unchanged.


46) Explain how const affects code safety (not “definition”).

Answer: const reduces accidental rebinding, making data flow more predictable and enabling safer refactors. But it doesn’t guarantee deep immutability unless you freeze or use persistent structures.


47) Why does JSON.stringify drop undefined and functions?

Answer: JSON has no representation for them. In objects they are omitted; in arrays they become null. This can cause data loss in serialization.


48) What’s the difference between “missing property” and “property with value undefined”?

Answer: Missing: !("x" in obj) or obj.hasOwnProperty("x") false. Explicit undefined: property exists but value is undefined. This affects iteration and serialization.


49) Why does typeof never return "null"?

Answer: Because of the legacy typeof null === "object" bug. For null, check explicitly: value === null.


50) What’s the most robust way to detect “plain objects”?

Answer: Depends on definition, but commonly:

  • Object.prototype.toString.call(x) === "[object Object]" and

  • prototype is Object.prototype (or null) for stricter checks. This avoids arrays, dates, functions, etc.


If you say “Next” , I’ll generate Batch 2 (51–100): Advanced Core (closures, prototypes, this, call/apply/bind, event loop, microtasks).

Last updated