Challenge 2: Fix a Layout-Thrashing Loop — Possible Solution ==================================================================== // Original, thrashing version: // for (const el of elements) { // const height = el.offsetHeight; // READ // el.style.width = `${height * 2}px`; // WRITE — interleaved with reads // } // Batched version: const heights = elements.map((el) => el.offsetHeight); // ALL reads first elements.forEach((el, i) => { el.style.width = `${heights[i] * 2}px`; // ALL writes after }); WHY THIS WORKS -------------- - The first pass — elements.map((el) => el.offsetHeight) — does NOTHING but read layout properties, for every element, before any style is ever written. Because no write happens between any of these reads, the browser can safely reuse its existing, already-computed layout information for each subsequent read rather than being forced to recalculate it fresh each time. - The second pass — the forEach writing el.style.width — does NOTHING but write styles, using the heights ALREADY CAPTURED in the first pass rather than re-reading offsetHeight again. Since no reads happen during this pass, none of these writes force an immediate, synchronous layout recalculation the way an interleaved read would. - This directly eliminates the thrashing pattern the chapter describes: in the original version, each write invalidates the browser's cached layout info, so the VERY NEXT read (for the next element) can't reuse anything — it has to trigger a fresh, synchronous recalculation just to answer that one offsetHeight query. With 50 elements interleaved this way, that could mean up to 50 separate forced layout recalculations; the batched version does the layout work once, reading everything needed before touching anything that would invalidate it. - Storing the read results in the heights array (rather than re-reading offsetHeight during the second loop) is the key structural change that makes the "read everything, then write everything" separation actually possible — without capturing the values up front, the second loop would have no choice but to re-read from the DOM, reintroducing the exact interleaving this fix is meant to avoid.