Test your knowledge of essential JavaScript scenarios with this easy, interview-oriented quiz. Assess your understanding of JavaScript event loop, microtasks, memory leaks, and best practices—all relevant for developers preparing for 2025 challenges.
When a JavaScript single-page app shows UI flicker after users click quickly, what is the likely cause related to microtasks and macrotasks?
Explanation: Microtasks (like Promises) are executed before macrotasks (like setTimeout), so if too many microtasks run, they can delay the browser’s chance to render, creating UI flicker. Timers not firing would typically result in missed events rather than flicker. Macro tasks do not finish before microtasks; microtasks always run first. Event listeners are not removed automatically, so the fourth option is incorrect.
If a Node.js HTTP server experiences CPU spikes during peak traffic even though there are few I/O operations, what should you check first?
Explanation: Synchronous JavaScript can block the Node.js event loop, causing CPU to spike and latency to increase. Increasing database connections won’t help if the code is blocked. Simply switching to Promises does not resolve blocking if the logic is still synchronous. Disabling caching may impact performance but won't solve CPU event loop blocking.
In which code area should optional chaining (?.) generally be avoided for best performance?
Explanation: Optional chaining is best used when values might be absent, such as incoming API data, configs, or feature flags. In tight inner loops where data is validated and guaranteed, using optional chaining can hide bugs and reduce performance slightly. The other options represent scenarios where optional chaining improves safety and code clarity.
After moving to ES modules, you notice a setTimeout callback runs after a Promise thenable. Why does this happen?
Explanation: JavaScript always finishes all microtasks (such as resolved Promises) before handling the next macrotask (like setTimeout). setTimeout does not run before a microtask; the opposite is true. ES modules do not affect callback queue order. Promise callbacks are never ignored by browsers under normal operation.
Which is a common source of memory leaks in JavaScript web applications after long user sessions?
Explanation: Attaching event listeners to DOM nodes that are later removed from the DOM but not properly cleaned up can cause memory leaks. Variables declared with let are local and cleaned up when the function ends. CSS hover effects are not related to JavaScript memory. Removing objects from global scope helps, rather than hurts, memory usage.
If a function in a Node.js service is doing heavy computation that blocks the event loop, what is an effective solution?
Explanation: Offloading heavy work to a worker or child process allows the main event loop to stay responsive. Increasing callbacks won’t help if the work remains synchronous. Adding more event listeners increases memory overhead but does not solve blocking. Using eval is unrelated and introduces security and performance issues.
You notice UI state flicker when multiple setTimeout and Promise callbacks are used together in a component. What is a good approach to fix this?
Explanation: Batching state changes inside a single microtask ensures predictable updates and reduces flicker. Chaining setTimeouts can make the issue worse by increasing the unpredictability of updates. Adding global variables is not a solution and can introduce bugs. Disabling user events hinders usability and is not necessary for flicker management.
Which operator should you combine with optional chaining to provide a fallback value when accessing nested properties?
Explanation: The nullish coalescing operator (??) returns the right-hand value when the left is null or undefined, making it a good companion for optional chaining. The bitwise AND operator does not deal with undefined or null. Logical OR (||) sometimes produces unexpected results if valid falsy values like 0 or empty strings are needed. The not-equals operator is not suitable for value selection.
Why should you always clear timers and intervals in JavaScript when navigating between pages or components?
Explanation: Timers and intervals, if not cleared, can keep running and reference old data, leading to memory leaks and unwanted repeated execution. Timers alone are not the cause of slow transitions. Clearing them has no effect on styles. Intervals are not cleared automatically by navigation; manual cleanup is required.
Which testing practice helps avoid broken tests after refactoring timer and Promise code in JavaScript modules?
Explanation: Awaiting Promises produced by your code provides explicit control over async behavior and avoids assumptions about scheduling. Assuming timers always fire immediately is unreliable and not true across all environments. Hardcoding callback order is brittle and makes tests less robust. Disabling microtasks is not practical or generally available in test tools.
How can you prevent a global cache object from causing memory leaks in a JavaScript application?
Explanation: Imposing size limits and eviction policies keeps the cache from growing uncontrollably and consuming memory. Increasing object references compounds leaks. Choice of `var` for cache keys does not impact memory management. Storing cache values as strings doesn’t prevent memory leaks if unused entries are never removed.
To avoid memory leaks, what should you do with MutationObserver or IntersectionObserver instances when a component is destroyed?
Explanation: Disconnecting observers releases their references and callbacks, preventing leaks after components are destroyed. Simply creating new observers does not clean up the old ones. Garbage collection may not help if references remain active. Removing from arrays does not affect the observer’s attachment to the DOM.
Why should you be cautious about closures that capture large objects in JavaScript?
Explanation: Closures hold onto referenced variables as long as the closure exists, which is problematic with large objects. Syntax errors are unrelated to closure size. Large objects generally slow down code, not speed it up. Closures are valid inside loops; the problem is retention, not syntax.
What is a robust practice before accessing deeply nested optional data in JavaScript?
Explanation: Validating data once upfront ensures safety and avoids unnecessary repeated checks, leading to better performance in loops. Adding optional chaining everywhere adds redundant overhead. Bracket notation does not protect against undefined references. Forcing type casts can hide errors if data is not valid.
Abuse of which method can starve the event loop phases in Node.js, blocking timers and I/O callbacks?
Explanation: Overusing process.nextTick can prevent the event loop from handling timers and I/O by flooding the next tick queue. setInterval schedules repeated work but doesn’t directly starve the loop. console.log affects performance if overused but does not block the event loop. require is used for imports and not related to event loop starvation.
Which JavaScript scheduling method best aligns work with the browser's next paint for smoother UI updates?
Explanation: requestAnimationFrame schedules a callback right before the next browser paint, making it ideal for smooth visual updates. setTimeout with zero delay does not align with rendering timing precisely. setInterval is for repeated intervals and not meant for animation pacing. Promise.resolve with then runs microtasks, which always occur before rendering.