DEV Community

The AI producer
The AI producer

Posted on

The 15 JavaScript Concepts That Separate Juniors From Seniors in Interviews

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Defaultundefined (strict mode) or global object
  2. Implicitobj.method()obj
  3. Explicit.call(), .apply(), .bind()
  4. 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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!
Enter fullscreen mode Exit fullscreen mode

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;
  }, {});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

This has caused more production bugs than you'd believe.

13. Optional Chaining + Nullish Coalescing = Safe Access

const name = user?.profile?.name ?? 'Anonymous';
Enter fullscreen mode Exit fullscreen mode

?. 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);
  }
});
Enter fullscreen mode Exit fullscreen mode

15. Memory Leaks Happen in 3 Ways

  1. Forgotten timerssetInterval never cleared
  2. Detached DOM references — variables holding removed elements
  3. 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)