After creating interview prep guides across 10 different technologies, I noticed the same JavaScript concepts come up again and again — and the same ones trip people up. Here are the 15 that actually matter, with the quick version of what interviewers are really testing.
1. Closures Aren't Just "Functions Inside Functions"
A closure isn't the nested function itself — it's the combination of the function and its lexical environment. Interviewers test whether you understand that the inner function remembers the variables from where it was defined, not where it was called.
function counter() {
let count = 0;
return () => ++count; // This arrow function closes over `count`
}
const c = counter();
c(); // 1
c(); // 2
What they're testing: Do you understand scope persistence, or do you just know the buzzword?
2. this Has Exactly 4 Binding Rules
Stop guessing. this is determined by:
-
Default —
undefined(strict mode) or global object -
Implicit —
obj.method()→obj -
Explicit —
.call(),.apply(),.bind() -
new— the newly created object
Arrow functions ignore all of these — they inherit this from their lexical scope.
3. The Event Loop: Microtasks Beat Macrotasks
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Output: 1, 4, 3, 2
Why: Promises (microtasks) drain completely before setTimeout (macrotask) gets a turn. This single distinction explains 80% of async interview questions.
4. let and const Are Hoisted Too — Just Not Initialized
console.log(x); // ReferenceError (Temporal Dead Zone)
let x = 5;
var hoists AND initializes to undefined. let/const hoist but throw if you access before declaration. This is the Temporal Dead Zone.
5. == vs === — Memorize the Weird Ones
null == undefined // true (the ONLY case)
NaN == NaN // false
[] == false // true (yes, really)
'' == 0 // true
In interviews, just say "always use === except when checking null/undefined with x == null."
6. Prototypal Inheritance Is a Chain, Not a Tree
Every object has a __proto__ pointing to its constructor's prototype. The chain ends at Object.prototype.__proto__ which is null. instanceof walks this chain.
7. Object.assign Is Shallow. So Is Spread.
const obj = { a: { b: 1 } };
const copy = { ...obj };
copy.a.b = 99;
console.log(obj.a.b); // 99 — nested objects are shared!
For deep clones: structuredClone(obj) (built-in, handles most cases) or JSON.parse(JSON.stringify(obj)) (no functions/dates/undefined).
8. reduce Is More Powerful Than You Think
It's not just for sums. It can build any data transformation:
const groupBy = (arr, key) =>
arr.reduce((acc, item) => {
(acc[item[key]] ||= []).push(item);
return acc;
}, {});
9. Debounce vs Throttle — Know the Difference
- Debounce: "Wait until they STOP, then fire." (Search autocomplete)
- Throttle: "Fire at most once per X ms." (Scroll/resize handlers)
10. async/await Is Syntactic Sugar Over Promises
Every async function returns a Promise. await pauses execution until the Promise resolves. Error handling uses try/catch instead of .catch(). Under the hood, it's all generators and promises.
11. WeakMap and WeakSet Exist for a Reason
They don't prevent garbage collection of keys. Use them when you want to associate data with objects without keeping those objects alive — like caching metadata on DOM nodes.
12. Array.sort() Mutates and Sorts as Strings by Default
[10, 1, 2, 21].sort(); // [1, 10, 2, 21] — lexicographic!
[10, 1, 2, 21].sort((a, b) => a - b); // [1, 2, 10, 21] — numeric
This has caused more production bugs than you'd believe.
13. Optional Chaining + Nullish Coalescing = Safe Access
const name = user?.profile?.name ?? 'Anonymous';
?. short-circuits to undefined. ?? only catches null/undefined (not 0 or ''), unlike ||.
14. Event Delegation Beats Individual Listeners
// One listener handles all current and future buttons
document.addEventListener('click', (e) => {
if (e.target.matches('.dynamic-btn')) {
handleClick(e.target);
}
});
15. Memory Leaks Happen in 3 Ways
-
Forgotten timers —
setIntervalnever cleared - Detached DOM references — variables holding removed elements
- Closures holding large scopes — unintentionally retaining big objects
What Now?
If you're prepping for interviews, the full versions of these concepts (plus 150+ more questions with model answers and follow-ups) are in the developer interview guide collection I put together:
JavaScript, Python, TypeScript, Docker/K8s, AWS, SQL, React, and System Design guides →
And if you just want free tools (no signup), I built 68 free developer utilities that run entirely in your browser.
What JavaScript concept tripped you up in an interview? I'd love to hear the ones I missed.
Cover image: abstract geometric pattern representing JavaScript's event loop.
Top comments (0)