<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Aditya Dutta on Medium]]></title>
        <description><![CDATA[Stories by Aditya Dutta on Medium]]></description>
        <link>https://medium.com/@developer.ad07?source=rss-a353cab2e24f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*KRHfI9JeqyQjkvcQ</url>
            <title>Stories by Aditya Dutta on Medium</title>
            <link>https://medium.com/@developer.ad07?source=rss-a353cab2e24f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 21:22:46 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@developer.ad07/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Finally, a <select> I Can Style Without Rebuilding It in JS]]></title>
            <link>https://medium.com/@developer.ad07/finally-a-select-i-can-style-without-rebuilding-it-in-js-076a5834340e?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/076a5834340e</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[ui-design]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[html5]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Wed, 28 Oct 2026 08:14:10 GMT</pubDate>
            <atom:updated>2026-10-28T08:14:10.358Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hPfko99T9Py3eZGQxxa2og.jpeg" /></figure><h3>The little HTML element that never matched the design</h3><p>I’ve lost count of how many times I’ve styled a form, felt happy with the result, and then reached the dropdown.</p><p>The input fields looked clean. The buttons matched the design system. The spacing was consistent.</p><p>And then there was &lt;select&gt;.</p><p>It looked like it belonged to a completely different website.</p><h3>The problem with native dropdowns</h3><p>A native dropdown is one of the simplest things to build in HTML.</p><pre>&lt;label for=&quot;country&quot;&gt;Choose a country&lt;/label&gt;<br>&lt;select id=&quot;country&quot; name=&quot;country&quot;&gt;<br>  &lt;option value=&quot;us&quot;&gt;United States&lt;/option&gt;<br>  &lt;option value=&quot;ca&quot;&gt;Canada&lt;/option&gt;<br>  &lt;option value=&quot;in&quot;&gt;India&lt;/option&gt;<br>&lt;/select&gt;</pre><p>No JavaScript. No dependencies. Just HTML.</p><p>But when the design calls for rounded corners, custom colors, a different arrow, styled options, and a highlighted selected item, things get complicated.</p><p>You can style parts of a native &lt;select&gt;, but the opened dropdown menu has traditionally been controlled largely by the browser and operating system.</p><p>That is where the familiar workaround begins.</p><h3>So, we rebuild it in JavaScript</h3><p>We hide the original dropdown and create a custom one using buttons, divs, event handlers, and CSS.</p><p>Then we handle opening and closing, track the selected option, support keyboard navigation, manage focus, and make the component work with forms.</p><p>Suddenly, a tiny dropdown has become a component of its own.</p><p>Libraries such as Select2 and Choices.js can help, especially when you need advanced functionality.</p><p>But sometimes, all you wanted was a dropdown that matched your design.</p><p><strong>What if CSS could handle more of that work without throwing away the native </strong><strong>&lt;select&gt;?</strong></p><p>It now can, in browsers that support customizable select elements.</p><h3>Meet appearance: base-select</h3><p>The modern approach starts with a CSS property:</p><pre>select,<br>select::picker(select) {<br>  appearance: base-select;<br>}</pre><p>That second selector is the interesting part.</p><p>appearance: base-select opts the control into a customizable rendering model. The ::picker(select) pseudo-element targets the dropdown menu itself.</p><p>Instead of styling only the closed control, you can customize both the button and the list of options using CSS.</p><p>No JavaScript is required just to change the dropdown’s appearance.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*12_oXn8pIrzFNFP3DbP1mQ.png" /></figure><h3>Let’s style a real dropdown</h3><p>First, give the select a cleaner button style.</p><pre>select {<br>  width: 100%;<br>  padding: 12px 16px;<br>  border: 1px solid #d1d5db;<br>  border-radius: 10px;<br>  background: #ffffff;<br>  color: #172554;<br>  font: inherit;<br>  cursor: pointer;<br>}</pre><p>Now enable the customizable rendering model and style the dropdown menu.</p><pre>select,<br>select::picker(select) {<br>  appearance: base-select;<br>}<br>select::picker(select) {<br>  padding: 6px;<br>  border: 1px solid #e5e7eb;<br>  border-radius: 12px;<br>  background: #ffffff;<br>  box-shadow: 0 12px 30px rgb(0 0 0 / 10%);<br>}</pre><p>The menu can now have its own border, spacing, background, and shadow.</p><p>That is a meaningful difference from the traditional approach, where the opened menu often resisted the styling you wanted.</p><h3>And yes, you can style individual options</h3><p>The options do not have to look like a plain list anymore.</p><pre>select option {<br>  padding: 10px 12px;<br>  border-radius: 8px;<br>}<br>select option:checked {<br>  background: #ccfbf1;<br>  color: #115e59;<br>}</pre><p>The :checked pseudo-class targets the selected option, allowing you to give it a distinct visual treatment.</p><p>You can also customize the dropdown arrow with ::picker-icon and use :open to change the select&#39;s appearance while its menu is open.</p><p>These are CSS features designed specifically for customizable selects, not JavaScript tricks.</p><h3>What are these CSS selectors actually called?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uUyuFEo_RdYxUJem_KYDHQ.jpeg" /></figure><p>If the syntax looks unfamiliar, you are not alone.</p><p>Consider these examples:</p><pre>select::picker(select) { }<br>select::picker-icon { }<br>select:open { }<br>select option:checked { }<br>select option::checkmark { }</pre><p>They might look similar, but each selector targets something different.</p><p><strong>1. </strong><strong>select — Type selector</strong></p><p>Targets the HTML &lt;select&gt; element itself: the dropdown control you see on the page.</p><p><strong>2. </strong><strong>::picker(select) — Pseudo-element</strong></p><p>Targets the dropdown picker that opens when you interact with the select. Think of it as the popup menu containing the options.</p><p><strong>3. </strong><strong>::picker-icon — Pseudo-element</strong></p><p>Targets the dropdown arrow inside the select button. You can customize its appearance instead of relying entirely on the default icon.</p><p><strong>4. </strong><strong>:open — Pseudo-class</strong></p><p>Targets the select while its picker is open. This is useful for changing the border, background, or other styles to indicate that the control is active.</p><p><strong>5. </strong><strong>:checked — Pseudo-class</strong></p><p>Targets the selected option, making it possible to distinguish the current choice from the other options.</p><p><strong>6. </strong><strong>::checkmark — Pseudo-element</strong></p><p>Targets the checkmark displayed alongside the selected option, allowing you to customize that indicator.</p><p>Here is how the selectors work together:</p><pre>/* The dropdown control */<br>select {<br>  border-radius: 10px;<br>}<br><br>/* The popup menu */<br>select::picker(select) {<br>  border-radius: 12px;<br>  padding: 6px;<br>}<br><br>/* The dropdown arrow */<br>select::picker-icon {<br>  color: teal;<br>}<br><br>/* When the dropdown is open */<br>select:open {<br>  border-color: teal;<br>}<br><br>/* The selected option */<br>select option:checked {<br>  background: #ccfbf1;<br>  color: #115e59;<br>}<br><br>/* The selected option&#39;s checkmark */<br>select option::checkmark {<br>  color: teal;<br>}</pre><p>The key distinction is simple: <strong>pseudo-classes describe a state, while pseudo-elements target a specific part of an element or its rendered content.</strong></p><p>Once you understand that difference, these selectors become much easier to read and remember.</p><h3>What about the JavaScript we used to write?</h3><p>Here is the part I like most about this change.</p><p>We have not replaced HTML with a clever new framework. We have not created another abstraction to maintain.</p><p>We have made an existing HTML element more customizable.</p><p>The native &lt;select&gt; still represents a form control. You can continue using its name, value, and normal form behavior.</p><p>In supporting browsers, you get much more control over its appearance without implementing the entire interaction model yourself.</p><p>That does not mean every custom dropdown library is unnecessary. Searchable selects, asynchronous options, tagging, and complex multi-select interactions can still justify a dedicated component.</p><p>The important difference is that <strong>visual customization no longer automatically means rebuilding the interaction in JavaScript.</strong></p><h3>Browser compatibility: What should you know?</h3><p>This is the part you should not skip.</p><p>Customizable select elements are a major improvement, but support depends on the browser and version. The appearance: base-select approach and its related selectors are not universally available in every browser.</p><p>Support for the main property does not necessarily guarantee support for every related pseudo-element or HTML enhancement.</p><p>Before using these features in production, check the current compatibility information for the exact features you intend to use.</p><p>You can start with <a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select">MDN’s customizable select guide</a> and its <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/appearance">CSS </a><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/appearance">appearance reference</a>.</p><h3>Use progressive enhancement</h3><p>The safest approach is to keep a functional native select as your foundation, then enable the advanced styling in browsers that support it.</p><pre>/* A useful baseline */<br>select {<br>  width: 100%;<br>  padding: 12px;<br>  border: 1px solid #d1d5db;<br>  border-radius: 10px;<br>}<br>/* Enhanced appearance in supporting browsers */<br>@supports (appearance: base-select) {<br>  select,<br>  select::picker(select) {<br>    appearance: base-select;<br>  }<br>  select::picker(select) {<br>    padding: 6px;<br>    border: 1px solid #e5e7eb;<br>    border-radius: 12px;<br>  }<br>}</pre><p>Browsers that do not support base-select can ignore the enhanced declarations and continue using the native control.</p><p>One important detail: @supports checks whether a declaration is recognized. It does not guarantee that every related pseudo-element or behavior works identically.</p><p>Test your actual target browsers, including mobile devices, and provide a sensible fallback wherever necessary.</p><h3>The bigger lesson</h3><p>Frontend development has a habit of turning small styling frustrations into large JavaScript components.</p><p>Sometimes that is necessary. Sometimes we are working around limitations that the platform is gradually removing.</p><p>Customizable &lt;select&gt; elements are a good reminder to revisit those old assumptions.</p><p>Before adding another dependency, ask yourself whether the browser can now do the job directly.</p><p>Because sometimes the best frontend abstraction is the one you no longer need to build.</p><p>And sometimes, all you wanted was a dropdown that matched your design.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=076a5834340e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JavaScript Memory: Where Do Your Variables Actually Live?]]></title>
            <link>https://medium.com/@developer.ad07/javascript-memory-where-do-your-variables-actually-live-8f541bf57529?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/8f541bf57529</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Thu, 22 Oct 2026 12:26:07 GMT</pubDate>
            <atom:updated>2026-10-22T12:26:07.606Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s0VHDuUnhGCMIp7DGD6JIw.png" /></figure><p>You write a variable, assign it a value, and use it somewhere in your code.</p><p>Simple enough.</p><p>But what happens when you assign an object to another variable? Why can changing one variable unexpectedly change the other? And why does an object sometimes remain in memory even after the function that created it has finished running?</p><p>These aren’t just JavaScript trivia questions. They explain some of the most confusing bugs you’ll encounter in real projects.</p><p>The interesting part is that <strong>a variable’s name, its value, and the memory holding that value are not necessarily the same thing.</strong></p><p>Let’s unpack that.</p><h3>A variable isn’t a little box you can always point to</h3><p>Consider this example:</p><pre>let age = 25;<br>let name = &quot;Alex&quot;;<br>let isDeveloper = true;</pre><p>It’s tempting to imagine three boxes sitting somewhere in memory, each containing one value.</p><p>That’s a useful beginner’s mental model. But JavaScript’s actual memory behavior is more complicated.</p><p>JavaScript creates bindings for these variables and associates them with values. The engine manages how those values are represented and stored internally.</p><p>For primitive values such as numbers, strings, and booleans, the details are often invisible to you.</p><p>Things become more interesting when objects enter the picture.</p><pre>const user = {<br>  name: &quot;Alex&quot;,<br>  age: 25<br>};</pre><p>Where does the object live? What does user actually hold?</p><p>To answer that, we need to understand two familiar terms: the stack and the heap.</p><h3>Stack vs. heap: The mental model that helps</h3><p>You have probably heard that JavaScript stores primitive values on the stack and objects on the heap.</p><p>This is a common teaching model, but there’s an important detail: <strong>JavaScript doesn’t require every engine to store values in exactly this way.</strong></p><p>The ECMAScript specification defines language behavior, not a universal physical memory layout. JavaScript engines can optimize storage and execution as they see fit.</p><p>Still, the stack-and-heap model is useful for understanding what’s happening.</p><p>Think of it this way:</p><ul><li><strong>Stack:</strong> Often associated with function calls, execution contexts, and short-lived local state.</li><li><strong>Heap:</strong> Commonly associated with dynamically allocated objects and other data that may outlive a particular function call.</li></ul><p>Imagine a function that creates an object.</p><pre>function createUser() {<br>  const name = &quot;Alex&quot;;<br>  const user = {<br>    name: name,<br>    active: true<br>  };<br>  return user;<br>}<br><br>const result = createUser();</pre><p>When createUser() executes, JavaScript establishes the function&#39;s execution context.</p><p>The function creates local bindings for name and user, and evaluates an object literal to create an object.</p><p>In a simplified stack-and-heap diagram, the local bindings belong to the function’s execution context, while the object is represented as an allocation in the heap.</p><p>When the function returns, its execution context can be discarded. But the returned object remains accessible through result.</p><p>That’s the first important insight: <strong>a function finishing doesn’t automatically mean everything it created must disappear.</strong></p><p>Whether data can be reclaimed depends on whether it remains reachable.</p><h3>The real surprise: Two variables, one object</h3><p>Now let’s look at a bug that appears in ordinary application code.</p><pre>const user = {<br>  name: &quot;Alex&quot;<br>};<br><br>const anotherUser = user;<br><br>anotherUser.name = &quot;Sam&quot;;<br><br>console.log(user.name);</pre><p>What do you expect the output to be?</p><p>It’s tempting to think that anotherUser received a copy of user. If that were true, changing one object wouldn&#39;t affect the other.</p><p>But the output is:</p><pre>&quot;Sam&quot;</pre><p>Why?</p><p>Because assigning an object to another variable doesn’t clone that object.</p><p>Both variables now provide access to the <strong>same underlying object</strong>.</p><p>Here’s a simplified representation:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pbt7-1ZMkF15AeG5nFVaFA.png" /></figure><pre>user ──────────┐<br>               ├────&gt; { name: &quot;Sam&quot; }<br>anotherUser ───┘</pre><p>The arrows represent the relationship between the variable bindings and the object. They aren’t literal pointers you can inspect in ordinary JavaScript.</p><p>When you run anotherUser.name = &quot;Sam&quot;, you modify that shared object. Reading user.name then returns the updated value because user still accesses the same object.</p><p>This is why copying objects requires more thought than assigning a variable.</p><h3>How to create a separate object</h3><p>If you want a shallow copy of this object, you can use the spread syntax:</p><pre>const user = {<br>  name: &quot;Alex&quot;<br>};<br><br>const anotherUser = { ...user };<br><br>anotherUser.name = &quot;Sam&quot;;<br><br>console.log(user.name);        // &quot;Alex&quot;<br>console.log(anotherUser.name); // &quot;Sam&quot;</pre><p>Now the two variables access different objects.</p><p>However, spread syntax creates only a shallow copy. If the object contains nested objects, those nested objects are still shared unless you copy them separately.</p><p>This distinction matters when managing form state, updating React state, editing configuration objects, and working with cached API responses.</p><p>A variable assignment can look harmless while creating shared mutable state across different parts of your application.</p><h3>Primitive values behave differently</h3><p>Compare object assignment with this example:</p><pre>let first = 10;<br>let second = first;<br><br>second = 20;<br><br>console.log(first);  // 10<br>console.log(second); // 20</pre><p>Here, changing second doesn&#39;t change first.</p><p>The difference isn’t simply that one value is stored on the stack and the other on the heap. The important language-level distinction is how assignment behaves.</p><p>For a primitive value, the receiving variable gets that value. Reassigning one binding doesn’t reassign the other.</p><p>For an object, the receiving variable gets the same object reference value. Mutating the object through either variable affects the same object.</p><p>JavaScript passes arguments by value, too. When the value is an object reference, the function receives a copy of that reference — not an independent copy of the object.</p><p>Consider this example:</p><pre>function updateUser(user) {<br>  user.name = &quot;Sam&quot;;<br>}<br><br>const person = {<br>  name: &quot;Alex&quot;<br>};<br><br>updateUser(person);<br><br>console.log(person.name); // &quot;Sam&quot;</pre><p>The function parameter receives a reference value that points to the same object. Mutating that object is visible to the caller.</p><p>But reassigning the parameter is different:</p><pre>function replaceUser(user) {<br>  user = { name: &quot;Sam&quot; };<br>}<br><br>const person = {<br>  name: &quot;Alex&quot;<br>};<br><br>replaceUser(person);<br><br>console.log(person.name); // &quot;Alex&quot;</pre><p>Reassigning user changes only the local parameter binding. It doesn&#39;t replace the caller&#39;s person binding.</p><p>Once you understand this distinction, many mysterious-looking JavaScript bugs become predictable.</p><h3>Why some variables survive after a function returns</h3><p>So far, we’ve seen that objects can remain accessible after the function that created them has finished.</p><p>Closures reveal an even more interesting version of this behavior.</p><p>Look at this function:</p><pre>function createCounter() {<br>  let count = 0;<br>  return function increment() {<br>    count++;<br>    return count;<br>  };<br>}<br><br>const counter = createCounter();<br>console.log(counter()); // 1<br>console.log(counter()); // 2<br>console.log(counter()); // 3</pre><p>The createCounter() function has already returned.</p><p>So why hasn’t count disappeared?</p><p>The returned increment function still has access to the lexical environment in which it was created. That environment includes the count binding.</p><p>As long as the returned function remains reachable, the engine must preserve the information needed for its behavior.</p><p>The engine may optimize how it represents that environment. It doesn’t have to keep an entire function execution context frozen on the stack.</p><p>But the observable behavior must remain the same: each call can access and update the same count binding.</p><p>This is a closure.</p><p><strong>A closure allows a function to retain access to variables from its surrounding lexical scope, even after that outer function has finished executing.</strong></p><p>Closures are useful for counters, private state, event handlers, callbacks, and functions that remember configuration.</p><p>They’re also a reminder that the lifetime of data isn’t always the lifetime of the function that created it.</p><h3>If memory can stay around, how does JavaScript clean it up?</h3><p>Imagine creating thousands of objects while using your application.</p><p>Eventually, some objects are no longer needed. If JavaScript kept all of them forever, applications would consume increasing amounts of memory.</p><p>This is where garbage collection comes in.</p><p>JavaScript engines use garbage collectors to reclaim memory occupied by data that is no longer needed. Modern engines commonly use reachability as a key part of deciding what can be collected.</p><p>Consider this example:</p><pre>let user = {<br>  name: &quot;Alex&quot;<br>};<br><br>user = null;</pre><p>Initially, user provides access to the object.</p><p>After user = null, that binding no longer provides access to it. If nothing else can reach the object, it becomes eligible for garbage collection.</p><p>Notice the wording: <strong>eligible for garbage collection</strong>.</p><p>Setting a variable to null doesn&#39;t immediately free the object&#39;s memory. The object might still be referenced elsewhere, and garbage collection timing is controlled by the engine.</p><p>For example:</p><pre>let first = {<br>  name: &quot;Alex&quot;<br>};<br><br>const second = first;<br><br>first = null;<br><br>console.log(second.name); // &quot;Alex&quot;</pre><p>The object remains accessible through second. Removing one reference doesn&#39;t make an object collectible when another reference still reaches it.</p><p>This is also why certain memory leaks happen.</p><p>An object may no longer be useful to your application but remain reachable through a long-lived reference, such as an event listener, timer, cache, or closure.</p><p>The garbage collector cannot safely discard an object that the program can still access.</p><h3>What this means for your real projects</h3><p>You don’t need to manually manage memory in everyday JavaScript. But understanding these relationships can help you write more predictable applications.</p><p>Keep these three situations in mind.</p><p><strong>1. When updating React state</strong></p><p>Avoid mutating an existing object when your intention is to create a new state value.</p><pre>// Avoid mutating the existing object<br>user.name = &quot;Sam&quot;;<br>setUser(user);<br>// Prefer creating a new object<br>setUser(previous =&gt; ({<br>  ...previous,<br>  name: &quot;Sam&quot;<br>}));</pre><p>The second approach creates a new object with the updated property. This works better with React’s state-update and identity-based comparison behavior.</p><p><strong>2. When managing event listeners</strong></p><p>A component that repeatedly registers listeners without removing obsolete ones can keep unnecessary work and references alive.</p><p>Clean up listeners when they’re no longer needed, particularly when attaching them to long-lived objects such as window or document.</p><p><strong>3. When caching data</strong></p><p>A cache can improve performance, but an unbounded cache can retain objects long after they’re useful.</p><p>Think about how entries are removed, whether the cache needs a size limit, and how long the cached data should remain available.</p><p>In all three situations, the useful question is the same: <em>What still has access to this data, and how long does that access need to last?</em></p><h3>The mental model worth remembering</h3><p>JavaScript memory becomes easier to understand when you stop imagining every variable as an isolated box.</p><p>Instead, think about three things:</p><ul><li><strong>Bindings:</strong> The names your code uses to access values.</li><li><strong>Objects and values:</strong> The data those bindings refer to or represent.</li><li><strong>Reachability:</strong> Whether the program can still access that data.</li></ul><p>The stack-and-heap model helps visualize how engines commonly manage execution and dynamically allocated data, but it isn’t a universal map of where every JavaScript value physically lives.</p><p>You don’t need to know the exact memory address of an object to understand why it survives, why two variables can modify the same data, or why a closure remembers a value.</p><p>The next time a JavaScript variable behaves unexpectedly, ask yourself one question:</p><p><strong>Did I change the variable, change the object it references, or change whether that object is still reachable?</strong></p><p>That question can lead you to the answer faster than staring at the assignment alone.</p><p><strong><em>#programming #webdevelopment #JavaScript #Software Development</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8f541bf57529" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I Built a JSON Explorer Because Finding One Value Shouldn’t Be This Hard]]></title>
            <link>https://medium.com/@developer.ad07/i-built-a-json-explorer-because-finding-one-value-shouldnt-be-this-hard-4c2dceb50a72?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/4c2dceb50a72</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[developer-tools]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Sat, 17 Oct 2026 12:59:14 GMT</pubDate>
            <atom:updated>2026-10-17T12:59:14.349Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0EYGU_-PZR4p-qVV-tjlUA.png" /></figure><p>There’s a particular kind of frustration every frontend developer knows.</p><p>You open an API response to find one value.</p><p>The JSON looks manageable at first. A few objects, some arrays, and a couple of nested properties.</p><p>Then you scroll.</p><p>And scroll.</p><p>And scroll some more.</p><p>The property you need is buried inside an object, which sits inside an array, which lives inside another object. You try searching for the key, but now you have multiple matches and no easy way to understand which one you actually need.</p><p>You could write a quick script. You could use an online formatter. Or you could keep digging through the response.</p><p>But I kept thinking: <strong>Why should finding one value inside JSON be this much work?</strong></p><p>That question became the starting point for a project I built called JSON Explore.</p><h3>The problem wasn’t JSON. It was working with JSON.</h3><p>JSON is everywhere in frontend development.</p><p>API responses, configuration files, mock data, application state, logs, and test fixtures all use it in one form or another.</p><p>Working with small JSON objects is easy.</p><p>The experience changes when the data gets larger.</p><p>Imagine an API response containing hundreds of users. Each user has an address, preferences, roles, and activity history. Some properties appear in several places, and some objects are nested multiple levels deep.</p><p>You want to find every occurrence of id.</p><p>A basic text search might find the word, but it doesn’t necessarily tell you where each value belongs in the data structure.</p><p>You need context.</p><p>You want to know the exact path, inspect the surrounding object, and understand whether you’re looking at the right value.</p><p>That’s where I saw an opportunity to build something more useful than another JSON formatter.</p><h3>I wanted one workspace, not another collection of tools</h3><p>I started building <strong>JSON Explore</strong> around a simple idea:</p><p>Bring your JSON into one workspace and keep it there while you work with it.</p><p>Instead of treating formatting, searching, querying, and inspecting as separate jobs, I wanted them to work with the same document.</p><p>Here’s what that looks like in practice.</p><p>Consider this JSON:</p><pre>{<br>  &quot;users&quot;: [<br>    {<br>      &quot;id&quot;: 101,<br>      &quot;name&quot;: &quot;Alice&quot;<br>    },<br>    {<br>      &quot;id&quot;: 102,<br>      &quot;name&quot;: &quot;Bob&quot;<br>    }<br>  ],<br>  &quot;admin&quot;: {<br>    &quot;id&quot;: 101,<br>    &quot;name&quot;: &quot;Admin&quot;<br>  }<br>}</pre><p>Suppose I want to find every occurrence of id.</p><p>Searching for the word alone isn’t enough. I want to know which objects contain it and how to reach each one.</p><p>JSON Explore can show matching paths such as:</p><pre>$.users[0].id<br>$.users[1].id<br>$.admin.id</pre><p>Now I can see the structure behind the matches rather than treating the response as a wall of text.</p><p>That small difference makes a tool much more useful during everyday debugging.</p><h3>Four problems I wanted to solve</h3><h3>1. Stop digging through nested objects</h3><p>The Explore tool presents JSON as an interactive tree.</p><p>Instead of reading every line, you can navigate the structure, inspect nodes, and search for keys or values.</p><p>The goal is simple: spend less time finding the data and more time understanding it.</p><h3>2. Find values by their paths</h3><p>Sometimes you already know where the value should be.</p><p>For example, you might want to inspect:</p><pre>users[].profile.email</pre><p>Or find every id property, regardless of how deeply it is nested:</p><pre>$..id</pre><p>JSON Explore supports simple path expressions and a subset of JSONPath syntax.</p><p>You don’t need to manually expand every object to locate the data you’re interested in.</p><h3>3. Understand the structure, not just the values</h3><p>Sometimes the problem isn’t finding a specific property.</p><p>You want to understand the entire document.</p><p>How many nodes does it contain? Which data types appear most often? What are the common keys? How deeply nested does the structure get?</p><p>The Statistics tool helps answer those questions.</p><p>This becomes particularly useful when inspecting unfamiliar API responses or trying to understand a dataset before working with it.</p><h3>4. Make large documents less painful</h3><p>A tool can feel great with a small example and become frustrating with a real-world payload.</p><p>Large JSON documents can make interfaces sluggish if parsing and searching block the browser’s main thread or if the UI tries to render every node at once.</p><p>I wanted JSON Explore to handle this more thoughtfully.</p><p>For large documents, it uses a Web Worker to move expensive processing away from the main thread. The tree is virtualized so the interface doesn’t need to render every node simultaneously.</p><p>These techniques don’t make every operation instant, but they help keep the interface responsive as the document grows.</p><h3>The decision I cared about most: keeping JSON in the browser</h3><p>There was another consideration beyond convenience.</p><p>JSON can contain sensitive information.</p><p>A developer might be inspecting an internal API response, customer records, application configuration, or data copied from a debugging session.</p><p>Pasting that information into an online tool introduces a reasonable question:</p><p><strong>Where does my data go after I paste it?</strong></p><p>For JSON Explore’s core workflow, I designed processing to happen locally in the browser.</p><p>Parsing, searching, querying, formatting, and statistics don’t require uploading the document to a backend.</p><p>That means the tool can help inspect JSON without sending its contents to a server.</p><p>Of course, this doesn’t make every JSON document safe to handle carelessly. Your browser environment and any extensions or scripts you run still matter. But avoiding unnecessary uploads is an important design choice.</p><p>For a developer utility, privacy shouldn’t have to be an afterthought.</p><h3>Building a developer tool taught me to think beyond features</h3><p>It’s easy to approach a project by listing features.</p><p>Add a search box. Add a formatter. Add a query panel. Add a statistics view.</p><p>But a collection of features doesn’t automatically create a good developer experience.</p><p>The more important questions are:</p><ul><li>Can someone find what they need without understanding the entire interface?</li><li>Can they switch between tasks without losing their current document?</li><li>Does the tool remain usable with larger inputs?</li><li>Can they inspect a result in context instead of receiving only a matching value?</li><li>Can they work with potentially sensitive data without unnecessary uploads?</li></ul><p>These questions changed how I thought about the project.</p><p>Performance isn’t just about making code execute faster. It’s also about keeping the interface usable.</p><p>Privacy isn’t just a statement on a landing page. It affects where processing happens.</p><p>And usability isn’t simply about having fewer clicks. It’s about helping developers understand their data with less effort.</p><p>Those principles are useful far beyond a JSON tool.</p><h3>Try it with your own JSON</h3><p>I built JSON Explore for a familiar problem, but I wanted it to be useful in real development work — not just in a demo.</p><p>You can paste JSON, upload a document, explore nested structures, search keys and values, run supported path queries, inspect statistics, and format valid JSON in the browser.</p><p>There’s no account to create before getting started.</p><p>If you regularly work with API responses or large JSON files, give it a try:</p><p><strong>Open JSON Explore</strong></p><p>I’d especially like to know where your current JSON workflow becomes frustrating.</p><p>Is it finding a deeply nested value? Comparing structures? Working with large responses? Or something else entirely?</p><p>I’m building this to solve practical developer problems, and that feedback can help determine what deserves attention next.</p><p>Because sometimes the most useful developer tools don’t come from inventing a completely new workflow.</p><p>They come from taking a familiar, frustrating task and asking a simple question:</p><p><strong>Can this be easier?</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c2dceb50a72" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[async/await vs Promises: The Difference Most JavaScript Developers Miss]]></title>
            <link>https://medium.com/@developer.ad07/async-await-vs-promises-the-difference-most-javascript-developers-miss-1bda575cd995?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/1bda575cd995</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Tue, 13 Oct 2026 07:41:07 GMT</pubDate>
            <atom:updated>2026-10-13T07:41:07.369Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uosEMXtWXO5PgcMbT6TcBw.png" /></figure><p>You need to fetch some data from an API.</p><p>You write a few lines of JavaScript, wait for the response, and update the UI. Everything works.</p><p>Then you encounter another developer using .then(), while you&#39;re using async/await.</p><p>Suddenly, a simple question appears: <strong>Which approach is better?</strong></p><p>If you’ve searched for this comparison, you’ve probably seen examples showing how async/await replaces Promise chains with cleaner-looking code.</p><p>But there’s something important those comparisons often miss.</p><p><strong>async/await and Promises aren&#39;t competing solutions. They work together.</strong></p><p>Understanding that difference makes it much easier to choose the right approach.</p><h3>First, let’s understand what a Promise actually does</h3><p>Imagine you’re building a product page.</p><p>The browser needs to request product details from an API. That request takes time, so JavaScript can’t immediately provide the final response.</p><p>This is where a Promise comes in.</p><p>A Promise represents the eventual result of an asynchronous operation. It can be pending, fulfilled, or rejected.</p><p>Here’s a simple example:</p><pre>fetch(&quot;/api/products&quot;)<br>  .then((response) =&gt; response.json())<br>  .then((products) =&gt; {<br>    console.log(products);<br>  })<br>  .catch((error) =&gt; {<br>    console.error(&quot;Something went wrong:&quot;, error);<br>  });</pre><p>Each .then() handles a successful step in the chain, while .catch() handles a rejection that reaches it.</p><p>The browser doesn’t need to stop everything while the request is in progress. Other JavaScript work can continue.</p><p>That’s the real value of Promises: they give us a way to work with results that aren’t available immediately.</p><p>But as the number of dependent steps grows, Promise chains can become harder to follow.</p><h3>Why async/await feels easier to read</h3><p>Now imagine you need to fetch a user, read their permissions, and then load their dashboard.</p><p>With Promise chains, you might write:</p><pre>fetchUser()<br>  .then((user) =&gt; fetchPermissions(user.id))<br>  .then((permissions) =&gt; fetchDashboard(permissions))<br>  .then((dashboard) =&gt; console.log(dashboard))<br>  .catch((error) =&gt; console.error(error));</pre><p>This is perfectly valid JavaScript.</p><p>However, when several steps depend on previous results, some developers find it harder to follow the flow.</p><p>Here’s the same sequence using async/await:</p><pre>async function loadDashboard() {<br>  try {<br>    const user = await fetchUser();<br>    const permissions = await fetchPermissions(user.id);<br>    const dashboard = await fetchDashboard(permissions);<br>    console.log(dashboard);<br>  } catch (error) {<br>    console.error(error);<br>  }<br>}</pre><p>Notice what changed.</p><p>The code reads more like a sequence of instructions. Each await makes the next step wait for the previous Promise to settle successfully.</p><p>You can see the dependency between operations without mentally tracing multiple .then() callbacks.</p><p><strong>That’s the main advantage of </strong><strong>async/await: it makes many asynchronous workflows easier to read and maintain.</strong></p><p>But it doesn’t replace the underlying Promise mechanism.</p><h3>Here’s the difference most developers miss</h3><p>Look at this function:</p><pre>async function getMessage() {<br>  return &quot;Hello, JavaScript!&quot;;<br>}</pre><p>It looks like the function returns a string.</p><p>It doesn’t. An async function always returns a Promise.</p><p>You can observe that behavior here:</p><pre>getMessage().then((message) =&gt; {<br>  console.log(message);<br>});</pre><p>The Promise fulfills with &quot;Hello, JavaScript!&quot;.</p><p>Even if you return an ordinary value, JavaScript wraps that value in a fulfilled Promise. If the function throws an error, its returned Promise rejects.</p><p>Now consider await:</p><pre>async function showMessage() {<br>  const message = await getMessage();<br>  console.log(message);<br>}</pre><p>await lets you work with the fulfilled value rather than explicitly attaching a .then() callback.</p><p>It doesn’t eliminate Promises. It changes how you write code that consumes them.</p><p>This distinction matters when you pass asynchronous functions to other functions, return values from them, or combine multiple requests.</p><h3>When should you use async/await?</h3><p>For most everyday asynchronous workflows, async/await is an excellent default.</p><p>Consider a form submission that needs to save a user’s profile.</p><pre>async function saveProfile(profile) {<br>  try {<br>    const response = await fetch(&quot;/api/profile&quot;, {<br>      method: &quot;POST&quot;,<br>      headers: {<br>        &quot;Content-Type&quot;: &quot;application/json&quot;,<br>      },<br>      body: JSON.stringify(profile),<br>    });<br>  if (!response.ok) {<br>      throw new Error(&quot;Failed to save profile&quot;);<br>    }<br>    const result = await response.json();<br>    console.log(&quot;Profile saved:&quot;, result);<br>  } catch (error) {<br>    console.error(&quot;Could not save profile:&quot;, error);<br>  }<br>}</pre><p>The flow is straightforward:</p><ol><li>Send the request.</li><li>Check whether the HTTP response indicates success.</li><li>Read the response body.</li><li>Handle errors.</li></ol><p>There’s another detail worth noticing: <strong>fetch() doesn&#39;t reject just because the server returns an HTTP error such as 404 or 500.</strong></p><p>That’s why the example checks response.ok explicitly.</p><p>This approach is useful for API requests, form submissions, authentication flows, and other operations where one step depends on another.</p><p>It also works naturally with try/catch, which many developers find easier to understand than rejection handlers spread across a long chain.</p><h3>But async/await can accidentally make your code slower</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MgnlQI1LIZy9t1sBj9vglg.png" /></figure><p>Here’s where the comparison gets interesting.</p><p>Suppose a dashboard needs to load the user’s profile and their notifications.</p><p>These two requests don’t depend on each other.</p><p>You might write:</p><pre>const profile = await fetchProfile();<br>const notifications = await fetchNotifications();</pre><p>This starts the second request only after the first one finishes.</p><p>If both requests could run independently, you’ve introduced unnecessary waiting.</p><p>The better approach is to start both operations before waiting for their results:</p><pre>const [profile, notifications] = await Promise.all([<br>  fetchProfile(),<br>  fetchNotifications(),<br>]);</pre><p>Now both operations can be in progress at the same time.</p><p>Promise.all() fulfills when all its input Promises fulfill. If any input Promise rejects, the combined Promise rejects.</p><p>This is one of the most useful patterns to remember when building frontend applications.</p><p><strong>The problem wasn’t </strong><strong>async/await. The problem was how the Promises were being coordinated.</strong></p><p>There’s an important caveat: Promise.all() doesn&#39;t cancel the other operations automatically when one rejects. Those operations may continue running.</p><p>Use it when you need all results and the operations can safely run independently.</p><h3>When Promises are the better tool</h3><p>So, should you stop using .then()?</p><p>Not at all.</p><p>Promises are especially useful when you’re coordinating asynchronous operations or composing results without needing a full sequential workflow.</p><p>For example, imagine you need to load three independent sections of a page:</p><pre>const requests = [<br>  fetchProfile(),<br>  fetchProducts(),<br>  fetchNotifications(),<br>];<br>Promise.all(requests)<br>  .then(([profile, products, notifications]) =&gt; {<br>    renderDashboard(profile, products, notifications);<br>  })<br>  .catch((error) =&gt; {<br>    console.error(&quot;Dashboard loading failed:&quot;, error);<br>  });</pre><p>You could write this using async/await too. Neither syntax has exclusive access to Promise.all().</p><p>The point is that Promises provide the coordination tools, while async/await provides another way to express the flow.</p><p>There are also cases where .then() is a natural fit, such as transforming a result in a short expression or working with an API that already returns a Promise chain.</p><p>Choose the form that makes the intent easiest to understand.</p><h3>One more mistake: assuming await handles every error</h3><p>Consider this example:</p><pre>async function loadProducts() {<br>  const response = await fetch(&quot;/api/products&quot;);<br>  return response.json();<br>}</pre><p>What happens if the request fails because of a network problem?</p><p>The function’s returned Promise rejects.</p><p>What happens if the server responds with HTTP 500?</p><p>The fetch() Promise can still fulfill with a Response object. Without checking response.ok, your code might try to process an error response as if it were successful data.</p><p>And what if the response body contains invalid JSON?</p><p>Reading it with response.json() can reject too.</p><p>Using await doesn&#39;t automatically make these errors disappear.</p><p>You still need to decide how your application should respond: show an error message, retry a request, use cached data, or let a higher-level error handler deal with it.</p><p>Good asynchronous code isn’t just about choosing readable syntax. It’s about making failure behavior explicit.</p><h3>My rule of thumb for real projects</h3><p>When deciding between the two, I use a simple mental model:</p><ul><li><strong>Use </strong><strong>async/await</strong> when you&#39;re describing a sequence of dependent operations.</li><li><strong>Use </strong><strong>Promise.all()</strong> when independent operations can run concurrently and you need all their results.</li><li><strong>Use </strong><strong>Promise.allSettled()</strong> when you want to inspect every operation&#39;s outcome, even if some fail.</li><li><strong>Use </strong><strong>.then() and </strong><strong>.catch()</strong> when a short Promise chain expresses the intent clearly.</li></ul><p>These aren’t strict rules. You can combine all these techniques in the same function.</p><p>For example, you can use async/await for the main workflow and Promise.all() for parallel requests inside it.</p><p>The goal isn’t to follow one syntax everywhere. It’s to make the relationships between asynchronous operations obvious.</p><h3>The takeaway</h3><p>The next time you compare async/await with Promises, don&#39;t ask which one is universally better.</p><p>Ask two more useful questions:</p><p><strong>How should these operations be coordinated? And which syntax makes that intention easiest to understand?</strong></p><p>Promises give JavaScript a way to represent and coordinate future results. async/await makes those results easier to work with in many situations.</p><p>Once you understand that relationship, choosing between them becomes much less confusing.</p><p>And your asynchronous code becomes easier to reason about — not because you picked the trendier syntax, but because you understood what your code actually needs to do.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1bda575cd995" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Does this Behave Differently in JavaScript?]]></title>
            <link>https://medium.com/@developer.ad07/why-does-this-behave-differently-in-javascript-6104d070dda7?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/6104d070dda7</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Tue, 06 Oct 2026 09:41:38 GMT</pubDate>
            <atom:updated>2026-10-06T09:41:38.383Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pUk8Y4h9Q3hBpnKB8AwJ_A.png" /></figure><p>If you’ve worked with JavaScript for a while, you’ve probably seen something like this:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  sayName() {<br>    console.log(this.name);<br>  }<br>};<br>user.sayName();</pre><p>Easy enough.</p><p>It prints:</p><pre>Aditya</pre><p>Then you make one small change:</p><pre>const sayName = user.sayName;<br><br>sayName();</pre><p>And suddenly:</p><pre>undefined</pre><p>Same function.</p><p>Same this.name.</p><p>Same JavaScript.</p><p>So what changed?</p><p><strong>The way the function was called.</strong></p><p>And this is the part of this that causes most of the confusion.</p><h3>this Doesn&#39;t Mean &quot;The Object Where the Function Lives&quot;</h3><p>A common assumption is:</p><blockquote>“<strong>this</strong> refers to the object that contains the function.&quot;</blockquote><p>That works in some situations, but it’s not the actual rule.</p><p>Consider:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  greet() {<br>    console.log(this.name);<br>  }<br>};<br>user.greet();</pre><p>Here, this refers to user.</p><p>Why?</p><p>Because the function is called like this:</p><pre>user.greet();</pre><p>The object before the dot becomes the receiver of the method call.</p><p>So:</p><pre>user.greet();</pre><p>means the function is called with user as its this.</p><p>But look at this:</p><pre>const greet = user.greet;<br>greet();</pre><p>Now there is no user. before the function call.</p><p>The function has been detached from the object.</p><p>And that’s where things start getting interesting.</p><h3>The Most Useful Rule for this</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R5giXkDhf6DOy4XFcuDHIw.png" /></figure><p>For <strong>regular functions</strong>, start with one question:</p><blockquote><strong>How was this function called?</strong></blockquote><p>Not:</p><blockquote><strong>Where was it created?</strong></blockquote><p>Not:</p><blockquote><strong>Which object contains it?</strong></blockquote><p>Not:</p><blockquote><strong>What variable name does it have?</strong></blockquote><p>Look at the call.</p><h3>Called as a method</h3><pre>user.greet();</pre><p>this → user</p><h3>Called as a standalone function</h3><pre>greet();</pre><p>this depends on the execution mode and environment.</p><p>In strict mode:</p><pre>function greet() {<br>  console.log(this);<br>}<br>greet();</pre><p>this is:</p><pre>undefined</pre><p>That’s why simply memorizing “this means the current object&quot; eventually breaks down.</p><h3>But Then Why Does This Work?</h3><p>Let’s make the example slightly more realistic.</p><pre>const counter = {<br>  count: 0,<br>  increment() {<br>    this.count++;<br>  }<br>};<br>counter.increment();<br>console.log(counter.count);</pre><p>The result is:</p><pre>1</pre><p>When JavaScript evaluates:</p><pre>counter.increment();</pre><p>the call is associated with counter.</p><p>So inside increment():</p><pre>this === counter</pre><p>And therefore:</p><pre>this.count++;</pre><p>is effectively modifying:</p><pre>counter.count++;</pre><p>This is why object methods using this feel natural.</p><h3>Now Detach the Function</h3><p>Here’s the bug that often surprises developers:</p><pre>const counter = {<br>  count: 0,<br>  increment() {<br>    this.count++;<br>  }<br>};<br>const increment = counter.increment;<br>increment();</pre><p>It looks like we’re still calling counter.increment().</p><p>But we’re not.</p><p>We’re calling:</p><pre>increment();</pre><p>The relationship with counter is gone.</p><p>This is one of the most important things to understand about JavaScript’s this:</p><blockquote><strong>Assigning a method to another variable does not preserve its original<em> </em></strong><strong><em>this.</em></strong></blockquote><p>The function itself didn’t change.</p><p><strong>The call changed.</strong></p><h3>And Then Arrow Functions Change the Rules</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2jhcjVjK2nG-cE0l5bO4yw.png" /></figure><p>Just when regular functions start making sense, arrow functions appear.</p><p>Consider:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  greet: () =&gt; {<br>    console.log(this.name);<br>  }<br>};<br>user.greet();</pre><p>You might expect:</p><pre>Aditya</pre><p>But you shouldn’t.</p><p>Arrow functions don’t create their own this.</p><p>Instead, they capture this from their surrounding lexical scope.</p><p>That’s a completely different behavior from regular functions.</p><h3>Regular Function vs Arrow Function</h3><p>Compare these:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  regular() {<br>    console.log(this.name);<br>  },<br>  arrow: () =&gt; {<br>    console.log(this.name);<br>  }<br>};<br>user.regular();<br>user.arrow();</pre><p>The regular function gets its this from the call:</p><pre>user.regular();</pre><p>The arrow function does <strong>not</strong>.</p><p>Its this comes from the surrounding scope where the arrow function was created.</p><p>This is why arrow functions are often useful inside callbacks.</p><h3>The Callback Problem</h3><p>Imagine:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  greet() {<br>    setTimeout(function () {<br>      console.log(this.name);<br>    }, 1000);<br>  }<br>};<br>user.greet();</pre><p>You might expect:</p><pre>Aditya</pre><p>But the regular function passed to setTimeout doesn&#39;t automatically inherit the this from greet().</p><p>This is where an arrow function can help:</p><pre>const user = {<br>  name: &quot;Aditya&quot;,<br>  greet() {<br>    setTimeout(() =&gt; {<br>      console.log(this.name);<br>    }, 1000);<br>  }<br>};<br>user.greet();</pre><p>Now the arrow function captures the surrounding this.</p><p>So the this inside the callback refers to the same this from greet().</p><p>This is one of the most practical reasons you’ll see arrow functions everywhere in frontend code.</p><h3>What About call(), apply(), and bind()?</h3><p>JavaScript also gives you explicit control over this.</p><p>For example:</p><pre>function greet() {<br>  console.log(`Hello ${this.name}`);<br>}<br>const user = {<br>  name: &quot;Aditya&quot;<br>};<br>greet.call(user);</pre><p>Now you’re explicitly saying:</p><blockquote><em>Call </em><em>greet with </em><em>user as </em><em>this.</em></blockquote><p>And JavaScript does exactly that.</p><p>You can also use bind():</p><pre>const boundGreet = greet.bind(user);<br>boundGreet();</pre><p>bind() creates a new function whose this is bound to user.</p><p>This is useful when you need to pass a method around without losing its context.</p><h3>So Which Rule Should You Remember?</h3><p>Instead of memorizing a huge list of special cases, start with this mental model:</p><h3>1. Regular function called as an object method</h3><pre>user.greet();</pre><p>this → user</p><h3>2. Regular function called by itself</h3><pre>greet();</pre><p>this depends on the execution mode.</p><p>In strict mode, it’s undefined.</p><h3>3. Arrow function</h3><pre>const greet = () =&gt; {};</pre><p>Arrow functions don’t create their own this.</p><p>They use the surrounding this.</p><h3>4. Explicit binding</h3><pre>greet.call(user);<br>greet.apply(user);<br>greet.bind(user);</pre><p>You explicitly control the this value.</p><h3>A Simple Way to Debug this</h3><p>When you encounter a confusing this, don&#39;t immediately search for a complicated explanation.</p><p>Instead, ask these questions:</p><p><strong>1. Is this a regular function or an arrow function?</strong></p><p>If it’s an arrow function, look at its surrounding scope.</p><p><strong>2. How is the function being called?</strong></p><p>Look at the actual call site.</p><pre>user.method();</pre><p>is different from:</p><pre>const method = user.method;<br>method();</pre><p><strong>3. Is </strong><strong>call(), </strong><strong>apply(), or </strong><strong>bind() involved?</strong></p><p>These can explicitly control this.</p><p><strong>4. Is the function running as a callback?</strong></p><p>Callbacks are a common place where this gets misunderstood.</p><p>This simple checklist solves a surprising number of this bugs.</p><h3>The Mistake Developers Often Make</h3><p>The biggest mistake is trying to understand this by looking only at the function definition.</p><p>For example:</p><pre>function greet() {<br>  console.log(this);<br>}</pre><p>Looking at this function alone doesn’t tell you what this will be.</p><p>You need to look at <strong>how </strong><strong>greet is called</strong>.</p><pre>user.greet();</pre><p>is one situation.</p><pre>greet();</pre><p>is another.</p><pre>greet.call(user);</pre><p>is another.</p><p>The function can be the same.</p><p>The this value can be different.</p><p>That’s the key.</p><h3>The Mental Model That Makes this Easier</h3><p>If there’s one idea worth remembering from this article, make it this:</p><blockquote><strong>For regular functions,<em> </em></strong><strong><em>this </em>is primarily determined by how the function is called.</strong></blockquote><p>And for arrow functions:</p><blockquote><strong><em>this </em>is inherited from the surrounding scope.</strong></blockquote><p>Once you understand those two ideas, a lot of JavaScript behavior stops looking random.</p><p>You no longer need to ask:</p><blockquote>“Why is JavaScript changing <strong>this</strong>?&quot;</blockquote><p>Instead, ask:</p><blockquote><strong><em>“</em>How was this function called?<em>”</em></strong></blockquote><p>That question will usually lead you to the answer.</p><p>JavaScript’s this isn&#39;t really unpredictable.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*txeLiEhZ47wSpBV8dpPWzQ.png" /></figure><p><strong>It’s contextual.</strong></p><p>And once you start looking at the call instead of the function itself, the behavior becomes much easier to reason about.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6104d070dda7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[You’re Already Using JavaScript Closures. You Just Don’t Know It]]></title>
            <link>https://medium.com/@developer.ad07/youre-already-using-javascript-closures-you-just-don-t-know-it-4e32274eca7b?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/4e32274eca7b</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Tue, 29 Sep 2026 07:20:06 GMT</pubDate>
            <atom:updated>2026-09-29T07:20:06.914Z</atom:updated>
            <content:encoded><![CDATA[<h3>JavaScript Closures: The Feature You Use Every Day Without Realising It</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wi0o1EQ-dKsRVvQu-XfQIg.png" /></figure><p>There’s a JavaScript concept that confuses almost every developer at some point.</p><h3><strong>“Closures”</strong></h3><p>The explanations usually make them sound much more complicated than they actually are.</p><p>You hear things like <em>lexical environment</em>, <em>execution context</em>, <em>scope chain</em>, and <em>persistent references</em>.</p><p>And suddenly a simple JavaScript function sounds like a compiler design lecture.</p><p>But here’s the interesting part:</p><p><strong>You probably use closures already.</strong></p><p>Event handlers.</p><p>setTimeout.</p><p>Callbacks.</p><p>Factory functions.</p><p>React hooks.</p><p>Even some of the small utility functions you write every day.</p><p>So instead of starting with a definition, let’s look at what actually happens.</p><h3>Start with this tiny example</h3><pre>function createCounter() {<br>  let count = 0;<br>  <br>  return function () {<br>    count++;<br>    return count;<br>  };<br>}<br>const counter = createCounter();<br>console.log(counter()); // 1<br>console.log(counter()); // 2<br>console.log(counter()); // 3</pre><p>At first glance, something strange is happening.</p><p>createCounter() has already finished running.</p><p>So where is count?</p><p>Why doesn’t it disappear?</p><p>And how does the returned function still know what count is?</p><p><strong>That’s a closure.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tAJ-sqa39xTWNxOnpAjtxw.png" /></figure><h3>The function remembers</h3><p>When createCounter() runs, it creates the variable:</p><pre>let count = 0;</pre><p>Then it returns another function.</p><p>That function uses count:</p><pre>return function () {<br>  count++;<br>  return count;<br>};</pre><p>Here’s the important part:</p><p>The returned function doesn’t just remember the code inside itself.</p><p>It also keeps access to the variables that were available in the scope where it was created.</p><p>So even after createCounter() finishes, the returned function can still access count.</p><p>That’s the key idea behind closures.</p><blockquote><strong>“A closure is a function together with access to the variables from the scope where that function was created.”</strong></blockquote><p>That’s it.</p><p>The concept sounds much scarier than the actual behavior.</p><h3>But why doesn’t count disappear?</h3><p>This is where closures become easier to understand.</p><p>Normally, you might think:</p><pre>function test() {<br>  let message = &quot;Hello&quot;;<br>}<br><br>test();</pre><p>After test() finishes, you can&#39;t access message.</p><pre>console.log(message); // Error</pre><p>And that’s correct.</p><p>message is local to test().</p><p>But now look at this:</p><pre>function test() {<br>  let message = &quot;Hello&quot;;<br>  return function () {<br>    console.log(message);<br>  };<br>}<br><br>const sayHello = test();<br><br>sayHello(); // Hello</pre><p>The outer function finished.</p><p>But the inner function still needs message.</p><p>JavaScript keeps the necessary variable accessible to that function.</p><p>That’s the important difference.</p><h3>Closures are not just about counters</h3><p>The counter example is popular because it’s easy to understand.</p><p>But closures become much more interesting when you see where they appear in everyday frontend code.</p><p>For example:</p><pre>function greetUser(name) {<br>  return function () {<br>    console.log(`Hello, ${name}`);<br>  };<br>}<br><br>const greetAditya = greetUser(&quot;Aditya&quot;);<br><br>greetAditya();</pre><p>The returned function remembers name.</p><p>You can create multiple independent functions:</p><pre>const greetAditya = greetUser(&quot;Aditya&quot;);<br>const greetRahul = greetUser(&quot;Rahul&quot;);<br><br>greetAditya(); // Hello, Aditya<br>greetRahul();  // Hello, Rahul</pre><p>Each function has access to its own surrounding state.</p><p>And that’s where closures become genuinely useful.</p><h3>You probably use closures with event handlers</h3><p>Consider a button:</p><pre>function setupButton(buttonId, message) {<br>  const button = document.getElementById(buttonId);<br>  button.addEventListener(&quot;click&quot;, () =&gt; {<br>    console.log(message);<br>  });<br>}<br>setupButton(&quot;saveButton&quot;, &quot;Saved successfully!&quot;);</pre><p>The click handler uses message.</p><p>But message belongs to setupButton().</p><p>Once setupButton() finishes, why can the click handler still access it?</p><p><strong>Closure.</strong></p><p>The event handler was created inside setupButton(), so it retains access to the variables from that surrounding scope.</p><p>This pattern appears everywhere in frontend development.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yhzYaEaE0SWoO9CbRDd-ng.png" /></figure><h3>And setTimeout does the same thing</h3><p>Here’s another example:</p><pre>function showMessage(message) {<br>  setTimeout(() =&gt; {<br>    console.log(message);<br>  }, 1000);<br>}<br><br>showMessage(&quot;Hello!&quot;);</pre><p>One second later, the callback still knows what message was.</p><p>Again:</p><p><strong>Closure.</strong></p><p>The callback remembers the surrounding variable.</p><p>This is one reason closures are so important in JavaScript.</p><p>You don’t usually write:</p><blockquote><strong>“I’m going to create a closure now.”</strong></blockquote><p>You simply write a callback.</p><p>JavaScript creates the closure as part of how that function works.</p><h3>Here’s where things get really useful</h3><p>Closures can also help you create <strong>private state</strong>.</p><p>JavaScript doesn’t require you to expose every variable.</p><p>For example:</p><pre>function createUser() {<br>  let points = 0;<br>  return {<br>      addPoint() {<br>        points++;<br>      },<br>      getPoints() {<br>        return points;<br>      }<br>    };<br>}<br><br>const user = createUser();<br>user.addPoint();<br>user.addPoint();<br><br>console.log(user.getPoints()); // 2</pre><p>Notice what you cannot do:</p><pre>console.log(user.points);</pre><p>There is no public points property.</p><p>But the returned methods can still access it because they close over the variable.</p><p>This gives you a simple form of encapsulation.</p><h3>The same idea appears in React</h3><p>If you’ve worked with React, closures aren’t some strange concept sitting outside your normal code.</p><p>They’re already part of it.</p><p>For example:</p><pre>function Counter() {<br>  const [count, setCount] = useState(0);<br>  <br>  function handleClick() {<br>      console.log(count);<br>    }<br>  return (<br>    &lt;button onClick={handleClick}&gt;<br>      {count}<br>    &lt;/button&gt;<br>  );<br>}</pre><p>handleClick can access count from the surrounding function.</p><p>That’s closure behavior.</p><p>React adds its own rendering and state model on top of this, so React’s behavior can involve more details than this simple example suggests.</p><p>But the underlying JavaScript concept is still there:</p><p><strong>A function can access variables from the scope where it was created.</strong></p><p>Understanding this makes a lot of JavaScript and React behavior feel less mysterious.</p><h3>But closures can also cause bugs</h3><p>Here’s the part developers sometimes learn the hard way.</p><p>Closures keep references to variables that a function still needs.</p><p>That can be useful.</p><p>But if you accidentally keep functions around longer than necessary, you can also keep related data reachable for longer than you intended.</p><p>For example, imagine creating a large object:</p><pre>function createHandler() {<br>  const largeData = createLargeObject();<br><br>  return function () {<br>      console.log(largeData);<br>    };<br>}<br>const handler = createHandler();</pre><p>As long as handler remains reachable and needs largeData, that data can remain reachable too.</p><p>This doesn’t mean:</p><p><strong>“Closures cause memory leaks.”</strong></p><p>That’s an oversimplification.</p><p>The real issue is <strong>unnecessary references that remain alive longer than needed</strong>.</p><p>Closures are just one mechanism that can contribute to that situation.</p><h3>One more closure example you should understand</h3><p>Look at this:</p><pre>function createMultiplier(multiplier) {<br>  return function (number) {<br>    return number * multiplier;<br>  };<br>}<br><br>const double = createMultiplier(2);<br>const triple = createMultiplier(3);<br>console.log(double(5)); // 10<br>console.log(triple(5)); // 15</pre><p>Something interesting happened here.</p><p>createMultiplier() created two functions.</p><p>But each function remembers a different value.</p><p>double remembers:</p><pre>multiplier = 2</pre><p>triple remembers:</p><pre>multiplier = 3</pre><p>That’s the power of closures.</p><p>You can create functions that carry their own surrounding state.</p><h3>So when should you actually care about closures?</h3><p>You don’t need to consciously think about closures every time you write a callback.</p><p>But understanding them becomes valuable when you’re working with:</p><ul><li>Event handlers</li><li>setTimeout and setInterval</li><li>Callbacks</li><li>Factory functions</li><li>Private state</li><li>Function generators</li><li>Memoization</li><li>Async code</li><li>React components and callbacks</li><li>State that needs to survive beyond a function call</li></ul><p>When something behaves like:</p><blockquote><strong>“How does this function still know that value?”</strong></blockquote><p>Closures are often part of the answer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lomiFDcZpZA0wl5aAGiNPQ.png" /></figure><h3>The mental model I use</h3><p>Don’t think about closures as some special JavaScript feature you need to memorise.</p><p>Think about them like this:</p><p><strong>A function remembers the environment it was created in.</strong></p><p>For example:</p><pre>function outer() {<br>  const name = &quot;JavaScript&quot;;<br><br>    return function inner() {<br>      console.log(name);<br>    };<br>}</pre><p>inner() was born inside outer().</p><p>So it can still access the variables that were available around it.</p><p>That’s the mental model.</p><p>Not:</p><blockquote><strong>“Closures are complicated lexical environments.”</strong></blockquote><p>But:</p><blockquote><strong>“This function can remember where it came from.”</strong></blockquote><p>Once you think about closures this way, a lot of JavaScript code becomes easier to reason about.</p><h3>The important takeaway</h3><p>Closures aren’t something you occasionally use when studying advanced JavaScript.</p><p>They’re already hiding inside the code you write.</p><p>That event handler?</p><p>Closure.</p><p>That timer callback?</p><p>Closure.</p><p>That factory function?</p><p>Closure.</p><p>That function that somehow still remembers a variable after the outer function finished?</p><p>Definitely closure.</p><p>The most useful thing to remember isn’t the textbook definition.</p><p>It’s this:</p><blockquote><strong><em>A function can keep access to variables from the scope where it was created, even after that outer function has finished running.</em></strong></blockquote><p>Once that clicks, closures stop feeling like magic.</p><p>They become one of the most natural parts of JavaScript.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4e32274eca7b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The DOM Is Not Your HTML: The Difference Every Frontend Developer Should Understand]]></title>
            <link>https://medium.com/@developer.ad07/the-dom-is-not-your-html-the-difference-every-frontend-developer-should-understand-1df212252e0c?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/1df212252e0c</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[html5]]></category>
            <category><![CDATA[html]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Thu, 17 Sep 2026 10:31:01 GMT</pubDate>
            <atom:updated>2026-09-17T10:31:01.579Z</atom:updated>
            <content:encoded><![CDATA[<p><em>You write HTML, but JavaScript doesn’t work directly with your HTML file. It works with the browser’s live DOM.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s4ZxfTuBPJDWlurlQe-4tw.png" /></figure><p>When you write HTML, you create the initial structure of a webpage. For example, your document might contain a simple heading:</p><pre>&lt;h1&gt;Hello&lt;/h1&gt;</pre><p>After the browser loads that page, JavaScript can find the heading and change its text:</p><pre>document.querySelector(&quot;h1&quot;).textContent = &quot;Hello World&quot;;</pre><p>The page now displays:</p><pre>&lt;h1&gt;Hello World&lt;/h1&gt;</pre><p>At first, this can make it seem as though JavaScript changed the HTML file itself. But that is not what happened. The original HTML file on the server still contains &lt;h1&gt;Hello&lt;/h1&gt;. JavaScript changed the browser&#39;s live representation of the page: the <strong>Document Object Model</strong>, or <strong>DOM</strong>. Understanding the difference between the HTML source and the DOM makes many JavaScript behaviours much easier to understand.</p><h3>HTML is a document. The DOM is a live representation.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bXt7C5QxubKS5_SeKfGcdA.png" /></figure><p>HTML is the markup you write.</p><p>For example:</p><pre>&lt;body&gt;<br>  &lt;h1&gt;Hello&lt;/h1&gt;<br>  &lt;button&gt;Click me&lt;/button&gt;<br>&lt;/body&gt;</pre><p>When the browser loads that document, it parses the HTML and creates a structure in memory.</p><p>That structure is the <strong>Document Object Model</strong>, or DOM.</p><p>You can think of it roughly like this:</p><pre>HTML<br> │<br> │ browser parses<br> ▼<br>DOM<br> │<br> ├── body<br> │    ├── h1<br> │    └── button</pre><p>The important part is that the DOM is not simply a copy of your HTML text.</p><p>It is a <strong>structured, programmable representation of the document</strong>.</p><p>That’s what JavaScript interacts with.</p><h3>So what does JavaScript actually change?</h3><p>Consider this:</p><pre>&lt;h1 id=&quot;title&quot;&gt;Hello&lt;/h1&gt;</pre><p>Then:</p><pre>const title = document.querySelector(&quot;#title&quot;);<br>title.textContent = &quot;Welcome&quot;;</pre><p>The JavaScript finds the DOM element and changes its text.</p><p>The DOM now represents:</p><pre>&lt;h1 id=&quot;title&quot;&gt;Welcome&lt;/h1&gt;</pre><p>But your original HTML source file hasn’t suddenly been rewritten.</p><p>If the HTML came from a server or a static file, that source still contains:</p><pre>&lt;h1 id=&quot;title&quot;&gt;Hello&lt;/h1&gt;</pre><p>This distinction is small, but extremely important.</p><p><strong>Changing the DOM is not the same thing as rewriting the HTML source.</strong></p><h3>Here’s an easy way to see the difference</h3><p>Open a webpage.</p><p>Then change something using JavaScript:</p><pre>document.querySelector(&quot;h1&quot;).textContent = &quot;Changed!&quot;;</pre><p>The page changes immediately.</p><p>Now compare:</p><p><strong>DOM</strong></p><pre>&lt;h1&gt;Changed!&lt;/h1&gt;</pre><p>with the original HTML source:</p><pre>&lt;h1&gt;Hello&lt;/h1&gt;</pre><p>They can now be different.</p><p>That’s because the browser is working with its live DOM representation.</p><h3>The DOM is more than what you originally wrote</h3><p>Here’s where things get even more interesting.</p><p>Suppose your HTML contains:</p><pre>&lt;ul id=&quot;users&quot;&gt;<br>  &lt;li&gt;John&lt;/li&gt;<br>&lt;/ul&gt;</pre><p>JavaScript can add another element:</p><pre>const list = document.querySelector(&quot;#users&quot;);<br>const item = document.createElement(&quot;li&quot;);<br>item.textContent = &quot;Sarah&quot;;<br>list.appendChild(item);</pre><p>The browser’s DOM now contains:</p><pre>ul<br>├── li &quot;John&quot;<br>└── li &quot;Sarah&quot;</pre><p>But you never added Sarah to the original HTML file.</p><p>The browser doesn’t need you to rewrite the source document.</p><p>JavaScript modified the live DOM.</p><p>This is one of the fundamental things behind interactive websites.</p><h3>The DOM is a tree</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ssD1HLQfVmOMGD-XjwF-_A.png" /></figure><p>The word <strong>Object Model</strong> can sound more complicated than it really is.</p><p>At its simplest, think of the DOM as a tree of nodes.</p><p>Given:</p><pre>&lt;main&gt;<br>  &lt;h1&gt;Hello&lt;/h1&gt;<br>  &lt;p&gt;Welcome!&lt;/p&gt;<br>&lt;/main&gt;</pre><p>The browser creates a structure roughly like:</p><pre>Document<br>   │<br>   └── main<br>       ├── h1<br>       │    └── &quot;Hello&quot;<br>       │<br>       └── p<br>            └── &quot;Welcome!&quot;</pre><p>That’s why JavaScript can navigate relationships such as:</p><pre>element.parentElement<br>element.children<br>element.nextElementSibling</pre><p>You’re not searching through a plain text file.</p><p>You’re working with a structured tree.</p><h3>And the DOM can change</h3><p>This is another important difference.</p><p>HTML source is generally the document you started with.</p><p>The DOM is <strong>live</strong>.</p><p>You can create elements:</p><pre>const button = document.createElement(&quot;button&quot;);</pre><p>Change attributes:</p><pre>button.setAttribute(&quot;disabled&quot;, &quot;&quot;);</pre><p>Change content:</p><pre>button.textContent = &quot;Loading...&quot;;</pre><p>And insert the element:</p><pre>document.body.append(button);</pre><p>The DOM changes as your application runs.</p><p>This is why we can build interactive interfaces without repeatedly downloading a completely new HTML document.</p><h3>But there is one more thing developers often confuse</h3><p>You might inspect a page and see HTML that wasn’t present in the original source.</p><p>For example, JavaScript might create:</p><pre>&lt;div class=&quot;notification&quot;&gt;<br>  Saved successfully<br>&lt;/div&gt;</pre><p>You didn’t write that element in the original HTML.</p><p>But browser developer tools can show it in the <strong>Elements</strong> panel.</p><p>That’s the DOM representation you’re looking at.</p><p>If you view the original page source, you may not find that element there.</p><p>So:</p><p><strong>View Source</strong> and <strong>Inspect Element</strong> are not necessarily showing you the same thing.</p><p>One important reason is that JavaScript can modify the DOM after the browser loads the original HTML.</p><h3>Why does this matter for frontend developers?</h3><p>Because a lot of frontend behaviour becomes easier to understand once you stop thinking:</p><blockquote><strong>“JavaScript changes the HTML.”</strong></blockquote><p>Instead, think:</p><blockquote><strong>“JavaScript changes the DOM.”</strong></blockquote><p>That mental model explains code like:</p><pre>element.classList.add(&quot;active&quot;);<br>element.remove();<br>element.textContent = &quot;Loading...&quot;;<br>element.append(newElement);</pre><p>All of these operate on the live document structure.</p><p>The browser can then use that changed DOM as part of the process of updating what you see on the screen.</p><h3>What about React?</h3><p>This distinction becomes even more useful when working with React.</p><p>You might write:</p><pre>return &lt;h1&gt;Hello&lt;/h1&gt;;</pre><p>But React doesn’t mean your JSX is literally the DOM.</p><p>JSX is syntax that describes UI.</p><p>React manages how that description should be reflected in the actual DOM.</p><p>That’s one reason it helps to understand the DOM before learning too much about framework abstractions.</p><p>Otherwise, concepts like rendering, reconciliation, refs, and DOM updates can feel unnecessarily mysterious.</p><p>You don’t need to know every internal detail.</p><p>Just remember:</p><pre>HTML<br>  ↓<br>Browser parses it<br>  ↓<br>DOM<br>  ↓<br>JavaScript can modify it<br>  ↓<br>Browser updates the rendered page</pre><p>Frameworks add another layer on top of this process, but the browser’s DOM is still there.</p><h3>One common mistake</h3><p>Developers sometimes assume that changing the DOM means they’ve changed the original HTML permanently.</p><p>They haven’t.</p><p>For example:</p><pre>document.body.innerHTML = &quot;&lt;h1&gt;New page&lt;/h1&gt;&quot;;</pre><p>This can replace the current document structure represented by the DOM.</p><p>But it doesn’t rewrite the HTML file on your server.</p><p>Refresh the page, and the browser loads the document again from its source.</p><p>Unless you’ve persisted the change somewhere and generated different HTML, the original document comes back.</p><p>That’s an important distinction between <strong>runtime state</strong> and <strong>source content</strong>.</p><h3>The mental model to remember</h3><p>Don’t think of this:</p><pre>HTML = DOM</pre><p>Think of it more like:</p><pre>HTML<br> │<br> │ parsed by browser<br> ▼<br>DOM<br> │<br> │ modified by JavaScript<br> ▼<br>Updated DOM<br> │<br> │ used during rendering<br> ▼<br>What the user sees</pre><p>The HTML is the document you provide.</p><p>The DOM is the browser’s live, structured representation of that document.</p><p>JavaScript interacts with the DOM.</p><p>And the browser uses the current document state when rendering the page.</p><h3>Final takeaway</h3><p>The DOM isn’t your HTML file.</p><p>HTML is markup.</p><p>The DOM is the browser’s live object-based representation of the document.</p><p>Once you understand that, several things become much clearer:</p><ul><li>Why JavaScript can add and remove elements</li><li>Why querySelector() works</li><li>Why textContent changes what you see</li><li>Why DevTools can show elements you never wrote in the original HTML</li><li>Why the DOM can change while the original source stays the same</li><li>Why frameworks like React still ultimately interact with the DOM</li></ul><p>The most useful mental shift is simple:</p><p><strong>You write HTML. The browser builds the DOM. JavaScript changes the DOM.</strong></p><p>Once that clicks, the DOM stops feeling like some mysterious JavaScript API and starts looking like what it really is:</p><p><strong>the browser’s live representation of your page.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1df212252e0c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The JavaScript Problem That Web Workers Were Built to Solve]]></title>
            <link>https://medium.com/@developer.ad07/the-javascript-problem-that-web-workers-were-built-to-solve-1a6fbc66c045?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a6fbc66c045</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[frontend-development]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Mon, 14 Sep 2026 10:31:01 GMT</pubDate>
            <atom:updated>2026-09-14T10:31:01.460Z</atom:updated>
            <content:encoded><![CDATA[<h3>JavaScript Workers: How to Run Code Without Freezing Your UI</h3><p><em>When JavaScript has too much work to do, the answer isn’t always more optimization. Sometimes, you need to move the work somewhere else.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1yag_CAwd6wYLjgfiFdECA.png" /></figure><p>Imagine this.</p><p>A user clicks a button.</p><p>The button changes to <strong>“Processing…”</strong></p><p>Everything looks correct.</p><p>But then the entire page stops responding.</p><p>The animation freezes.<br>Scrolling feels stuck.<br>Clicks don’t work.</p><p>Even though the browser hasn’t crashed.</p><p>This usually happens because JavaScript is doing too much work on the <strong>main thread</strong>.</p><p>And this is where Web Workers become interesting.</p><p>Instead of making the browser’s main JavaScript thread do everything, you can move certain heavy computations into a separate worker.</p><p>The UI gets room to breathe while the work continues.</p><h3>The problem: JavaScript can still block everything</h3><p>In the previous article, we looked at an important browser idea:</p><p><strong>JavaScript runs on a main thread, but the browser itself does much more than just run JavaScript.</strong></p><p>That doesn’t mean the main thread can never become a bottleneck.</p><p>It absolutely can.</p><p>Consider this:</p><pre>function calculate() {<br>  let total = 0;<br>  for (let i = 0; i &lt; 1_000_000_000; i++) {<br>      total += i;<br>    }<br>    return total;<br>  }<br>calculate();</pre><p>The code is valid.</p><p>The browser can execute it.</p><p>But while this loop is running, the main JavaScript thread is busy.</p><p>And if the main thread is busy with a long-running task, it can’t immediately handle other work that depends on it.</p><p>That’s when your UI starts feeling frozen.</p><h3>Why does the UI freeze?</h3><p>Here’s the part that is easy to miss.</p><p>Your button click, JavaScript execution, user interactions, and many tasks related to updating the page all compete for time on the browser’s main thread.</p><p>Now imagine this sequence:</p><pre>User clicks button<br>       ↓<br>JavaScript starts heavy calculation<br>       ↓<br>Main thread stays busy<br>       ↓<br>UI work has to wait<br>       ↓<br>Page feels frozen</pre><p>The browser isn’t necessarily broken.</p><p>Your code is simply occupying the thread for too long.</p><p>This is why a function that looks completely harmless can become a serious performance problem when the amount of data or computation grows.</p><h3>But what if the heavy work didn’t run there?</h3><p>This is the basic idea behind a Web Worker.</p><p>A Worker gives JavaScript another execution context that can run independently of the page’s main JavaScript execution.</p><p>Instead of doing this:</p><pre>MAIN THREAD<br>     │<br>     ├── UI<br>     ├── Events<br>     ├── JavaScript<br>     └── Heavy calculation  ← problem</pre><p>You can do this:</p><pre>MAIN THREAD                  WORKER<br>     │                         │<br>     ├── UI                    ├── Heavy calculation<br>     ├── User input            ├── Data processing<br>     └── Page logic            └── Result<br>             │                  │<br>             └── messages ─────┘</pre><p>The important word here is <strong>messages</strong>.</p><p>A Worker doesn’t magically share everything with your page.</p><p>You communicate with it.</p><h3>Your first Web Worker</h3><p>Let’s move the expensive calculation from the earlier example into a Worker.</p><h3>Main JavaScript</h3><pre>const worker = new Worker(&quot;worker.js&quot;);<br><br>worker.postMessage(1_000_000_000);<br><br>worker.onmessage = (event) =&gt; {<br>  console.log(&quot;Result:&quot;, event.data);<br>};</pre><p>And the Worker:</p><h3>worker.js</h3><pre>self.onmessage = (event) =&gt; {<br>  let total = 0;<br>  for (let i = 0; i &lt; event.data; i++) {<br>    total += i;<br>  }<br>  self.postMessage(total);<br>};</pre><p>That’s the basic Worker pattern.</p><p>The main thread sends data:</p><pre>worker.postMessage(...)</pre><p>The Worker receives it:</p><pre>self.onmessage = (...)</pre><p>The Worker does the work.</p><p>Then it sends the result back:</p><pre>self.postMessage(...)</pre><p>And the main thread receives it:</p><pre>worker.onmessage = (...)</pre><h3>What’s actually happening?</h3><p>Think of the Worker as a separate JavaScript worker that you give a job to.</p><p>The main thread says:</p><blockquote><strong>“Here’s the data. You handle this.”</strong></blockquote><p>The Worker performs the calculation.</p><p>When it’s finished, it sends a message back.</p><p>So instead of:</p><pre>Main thread<br>     ↓<br>Heavy calculation<br>     ↓<br>UI waits</pre><p>you get:</p><pre>Main thread ──→ Worker<br>     │             │<br>     │             └── Heavy calculation<br>     │<br>     └── continues handling the page</pre><p>That’s the important difference.</p><p><strong>The goal isn’t necessarily to make the calculation itself faster.</strong></p><p>The goal is to prevent that calculation from competing with the main thread’s UI work.</p><h3>Workers communicate through messages</h3><p>One of the biggest differences between normal JavaScript and Workers is how they communicate.</p><p>A Worker doesn’t simply reach into your page and change the DOM.</p><p>For example, this won’t work inside a Worker:</p><pre>document.querySelector(&quot;#result&quot;);</pre><p>A Worker doesn’t have direct access to the page’s DOM.</p><p>Instead, you communicate using messages.</p><pre>worker.postMessage(data);</pre><p>And receive messages with:</p><pre>worker.onmessage = (event) =&gt; {<br>  console.log(event.data);<br>};</pre><p>This separation is actually useful.</p><p>It forces you to make the data flow explicit.</p><pre>Main Thread<br>     │<br>     │ postMessage()<br>     ▼<br>  Worker<br>     │<br>     │ postMessage()<br>     ▼<br>Main Thread</pre><p>For many applications, that’s exactly the boundary you want.</p><h3>The old approach vs the better approach</h3><h3>❌ The problematic approach</h3><p>Imagine processing a huge dataset directly inside a button handler:</p><pre>button.addEventListener(&quot;click&quot;, () =&gt; {<br>  const result = processHugeDataset(data);<br>  renderResult(result);<br>});</pre><p>If processHugeDataset() takes a long time, the main thread is occupied while it runs.</p><p>The UI may become unresponsive.</p><h3>✅ The better approach</h3><p>Move the expensive computation into a Worker:</p><pre>const worker = new Worker(&quot;worker.js&quot;);<br><br>button.addEventListener(&quot;click&quot;, () =&gt; {<br>  worker.postMessage(data);<br>});<br><br>worker.onmessage = (event) =&gt; {<br>  renderResult(event.data);<br>};</pre><p>Now the expensive processing happens in the Worker.</p><p>The main thread can continue handling the page while it waits for the result.</p><h3>So what should actually go into a Worker?</h3><p>This is where developers sometimes overuse Workers.</p><p>You don’t need a Worker for every function.</p><p>A Worker becomes interesting when the task is <strong>CPU-heavy enough to compete with the main thread</strong>.</p><p>Good candidates include:</p><ul><li>Processing large datasets</li><li>Complex calculations</li><li>Large JSON transformations</li><li>Parsing large files</li><li>Image processing</li><li>Audio or video processing</li><li>Computational algorithms</li><li>Data compression or transformation</li><li>Some cryptographic or mathematical operations</li><li>Syntax highlighting or other expensive text processing</li></ul><p>The common pattern is simple:</p><p><strong>A lot of computation + little need for direct DOM access = good Worker candidate.</strong></p><h3>When you probably don’t need one</h3><p>Don’t create a Worker just because you can.</p><p>For a tiny operation like:</p><pre>const total = price * quantity;</pre><p>a Worker would add unnecessary complexity.</p><p>There is communication overhead, Worker startup cost, and another piece of code to manage.</p><p>For small tasks, normal JavaScript is usually the better choice.</p><p>The question shouldn’t be:</p><blockquote><strong>“Can I use a Worker?”</strong></blockquote><p>It should be:</p><blockquote><strong>“Is this work heavy enough that keeping it on the main thread hurts the user experience?”</strong></blockquote><p>That’s a much better question.</p><h3>Workers aren’t just about performance</h3><p>There’s another benefit that is easy to overlook.</p><p>Workers create a boundary.</p><p>Your UI code can focus on:</p><pre>Input<br>↓<br>State<br>↓<br>Display</pre><p>while the Worker focuses on:</p><pre>Input data<br>↓<br>Processing<br>↓<br>Output data</pre><p>That separation can make expensive processing easier to isolate and reason about.</p><p>But there is a trade-off.</p><p>You now have asynchronous communication, Worker lifecycle management, error handling, and data transfer to think about.</p><p>So Workers solve one problem while introducing some additional complexity.</p><p>That’s normal.</p><p>Good engineering isn’t about eliminating complexity.</p><p>It’s about putting complexity where it actually helps.</p><h3>There isn’t just one type of Worker</h3><p>When developers hear “Web Worker”, they often imagine one single API.</p><p>There are several Worker-related APIs, but they serve different purposes.</p><p>TypeMain purpose<strong>Dedicated Worker</strong>Run JavaScript work for a particular page/context<strong>Shared Worker</strong>Allow multiple browsing contexts to communicate with a shared Worker<strong>Service Worker</strong>Handle capabilities such as network interception, caching, and offline experiences</p><p>For heavy CPU-bound work, the <strong>Dedicated Worker</strong> is usually the concept you want to understand first.</p><p>A Service Worker is not simply a replacement for a Dedicated Worker.</p><p>They solve different problems.</p><h3>A few production details matter</h3><p>The basic example is small, but real applications need a little more care.</p><h3>Handle errors</h3><pre>worker.onerror = (error) =&gt; {<br>  console.error(&quot;Worker error:&quot;, error);<br>};</pre><h3>Stop a Worker when you no longer need it</h3><pre>worker.terminate();</pre><p>This can be useful when a Worker is temporary rather than something your application keeps around.</p><h3>Be careful with large data</h3><p>Messages between the main thread and a Worker involve data transfer.</p><p>Many JavaScript values are handled through the browser’s structured cloning mechanism.</p><p>For certain large binary datasets, <strong>Transferable objects</strong> can be used to transfer ownership rather than copying the data.</p><p>You don’t need to understand every detail on day one.</p><p>Just remember:</p><p><strong>Moving computation off the main thread doesn’t mean moving data is free.</strong></p><h3>What about React?</h3><p>React doesn’t change the underlying browser behavior.</p><p>If a React event handler performs a huge synchronous calculation:</p><pre>function handleClick() {<br>  const result = expensiveCalculation();<br>  setResult(result);<br>}</pre><p>that calculation still runs on the JavaScript execution context handling the page.</p><p>React can’t magically make CPU-heavy JavaScript disappear.</p><p>A Worker can be used as the computation layer instead:</p><pre>React UI<br>   │<br>   │ send data<br>   ▼<br>Web Worker<br>   │<br>   │ process data<br>   ▼<br>React UI</pre><p>This can be especially useful in applications where users interact with large datasets, editors, visualizations, or other computation-heavy interfaces.</p><p>The important part is not React.</p><p>It’s understanding <strong>which thread is doing the expensive work</strong>.</p><h3>The biggest mistake: using Workers for everything</h3><p>Workers are useful.</p><p>But they aren’t a performance button.</p><p>If your application is slow because of unnecessary rendering, excessive network requests, large assets, inefficient React updates, or poorly structured code, adding a Worker may not solve the actual problem.</p><p>First identify the bottleneck.</p><p>Then decide whether moving computation off the main thread makes sense.</p><p>A useful mental checklist is:</p><ol><li><strong>Is the task CPU-heavy?</strong></li><li><strong>Does it run long enough to affect responsiveness?</strong></li><li><strong>Does it need direct DOM access?</strong></li><li><strong>Can the input and output be passed through messages?</strong></li><li><strong>Is the added Worker complexity worth it?</strong></li></ol><p>If the answers line up, a Worker may be a very good fit.</p><h3>The mental model I want you to remember</h3><p>You don’t need to memorize the entire Worker API.</p><p>Remember this:</p><pre>MAIN THREAD<br>     │<br>     │ &quot;Here is the work.&quot;<br>     ▼<br>  WORKER<br>     │<br>     │ &quot;Here is the result.&quot;<br>     ▼<br>MAIN THREAD</pre><p>The main thread handles the page.</p><p>The Worker handles expensive JavaScript that can be isolated from the UI.</p><p>That simple separation can make the difference between an interface that feels frozen and one that stays responsive while the work happens.</p><h3>One important distinction</h3><p>There are two different performance problems developers often mix together.</p><p><strong>Problem 1: JavaScript is doing too much work.</strong></p><p>You may need to optimize the algorithm or reduce the amount of work.</p><p><strong>Problem 2: The work is legitimately expensive, but it doesn’t need to block the UI.</strong></p><p>That’s where a Worker becomes particularly useful.</p><p>A Worker doesn’t make bad code good.</p><p>It gives expensive code somewhere else to run.</p><p>And that’s a much more useful way to think about it.</p><h3>Final takeaway</h3><p>The browser gives your JavaScript a main thread that is critical to the responsiveness of your application.</p><p>If you occupy it with a huge calculation, the UI can suffer.</p><p>Web Workers give you another place to run JavaScript work without requiring that computation to happen on the page’s main execution thread.</p><p>The pattern is surprisingly simple:</p><p><strong>Send work → Worker processes it → Receive the result.</strong></p><p>You don’t need Workers everywhere.</p><p>You need them when expensive computation doesn’t belong in the same place as your UI work.</p><p>The next time a page feels frozen during a large calculation, don’t only ask:</p><p><strong>“How can I make this function faster?”</strong></p><p>Also ask:</p><p><strong>“Does this function need to run on the main thread at all?”</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a6fbc66c045" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why JavaScript Is Single-Threaded — but Your Browser Isn’t]]></title>
            <link>https://medium.com/@developer.ad07/why-javascript-is-single-threaded-but-your-browser-isnt-26753988c06e?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/26753988c06e</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Thu, 10 Sep 2026 07:56:07 GMT</pubDate>
            <atom:updated>2026-09-10T07:56:07.168Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8E-SlBjlV7RsvDR-OM3GPw.png" /></figure><p>JavaScript is single-threaded.</p><p>You have probably heard that sentence hundreds of times.</p><p>But then you open a modern website and somehow all of this happens together:</p><p>A network request is running.</p><p>An image is loading.</p><p>A CSS animation is moving.</p><p>The browser is responding to clicks.</p><p>The page is rendering.</p><p>And your JavaScript is still executing.</p><p>So what is actually going on?</p><p>If JavaScript has one thread, <strong>who is doing all the other work?</strong></p><p>The answer is one of the most useful things to understand about how browsers work:</p><p><strong>JavaScript is not the browser.</strong></p><h3>JavaScript has a main thread</h3><p>When frontend developers say JavaScript is single-threaded, they’re usually talking about the JavaScript execution model.</p><p>Your JavaScript code runs on a main JavaScript thread.</p><p>For example:</p><pre>console.log(&quot;One&quot;);<br>console.log(&quot;Two&quot;);<br>console.log(&quot;Three&quot;);</pre><p>These statements execute one after another.</p><p>JavaScript doesn’t normally execute these three pieces of code simultaneously on the same thread.</p><p>There is one call stack.</p><p>One piece of JavaScript runs at a time.</p><p>That’s what <strong>single-threaded</strong> means in this context.</p><p>But here’s where things get interesting.</p><p>The browser has responsibilities that go far beyond executing JavaScript.</p><h3>The browser has more jobs than running JavaScript</h3><p>A browser is a much larger system.</p><p>It has to deal with things like:</p><ul><li>Network requests</li><li>Timers</li><li>User input</li><li>Rendering</li><li>Image decoding</li><li>Audio</li><li>Video</li><li>Storage</li><li>Layout</li><li>Painting</li><li>Compositing</li><li>Other browser and operating-system work</li></ul><p>Your JavaScript isn’t personally performing all of these operations.</p><p>Instead, JavaScript can <strong>ask the browser to perform certain work</strong>.</p><p>For example:</p><pre>fetch(&quot;/api/users&quot;);</pre><p>Your JavaScript starts the request.</p><p>But JavaScript isn’t sitting there manually opening a network connection and moving every byte from the server.</p><p>The browser and its underlying systems handle that work.</p><p>When the result is ready, the browser can arrange for your JavaScript callback or promise continuation to run.</p><p>That’s a very different model from:</p><blockquote><strong><em>“</em>JavaScript does everything.”</strong></blockquote><h3>Think of JavaScript as one worker inside a much bigger system</h3><p>A useful mental model is to imagine a restaurant.</p><p>JavaScript is one worker taking orders.</p><p>The browser is the entire restaurant.</p><p>There are other workers handling different responsibilities.</p><p>JavaScript might say:</p><blockquote><strong>“I need this data from the server.”</strong></blockquote><p>The browser starts handling the network operation.</p><p>JavaScript doesn’t need to sit there doing nothing until every byte arrives.</p><p>Instead, it can continue with other JavaScript work.</p><p>Later, when the operation is ready to be observed by JavaScript, the relevant task can be scheduled for the JavaScript thread.</p><p>This is the basic idea behind asynchronous browser APIs.</p><h3>So what happens with fetch()?</h3><p>Consider this:</p><pre>console.log(&quot;Start&quot;);<br>fetch(&quot;/api/users&quot;)<br>  .then(() =&gt; {<br>    console.log(&quot;Users received&quot;);<br>  });<br>console.log(&quot;End&quot;);</pre><p>Many beginners initially imagine something like this:</p><pre>Start<br>   ↓<br>fetch()<br>   ↓<br>wait for server<br>   ↓<br>Users received<br>   ↓<br>End</pre><p>But that’s not what happens.</p><p>The JavaScript execution doesn’t simply stop at fetch() waiting for the network response.</p><p>Conceptually, the flow is closer to:</p><pre>JavaScript<br>   │<br>   ├── Start fetch<br>   │<br>   ▼<br>Browser handles network work<br>   │<br>   │<br>   └───────────────┐<br>                   │<br>JavaScript         │<br>continues          │<br>                   │<br>   ▼               │<br>console.log(&quot;End&quot;) │<br>                   │<br>                   ▼<br>        Response becomes available<br>                   │<br>                   ▼<br>        Promise continuation<br>        gets scheduled<br>                   │<br>                   ▼<br>        JavaScript runs it</pre><p>So the output is generally:</p><pre>Start<br>End<br>Users received</pre><p>The important part isn’t just that fetch() is asynchronous.</p><p>The important part is <strong>who is doing the waiting</strong>.</p><p>JavaScript isn’t blocking its thread waiting for the server response.</p><h3>The event loop connects the pieces</h3><p>This is where the event loop becomes important.</p><p>You can think of the JavaScript environment as having a place where JavaScript executes and mechanisms that coordinate when asynchronous work can continue.</p><p>A simplified model looks like this:</p><pre>Browser<br>                │<br>     ┌──────────┼───────────┐<br>     │          │           │<br> Network     Timers      User Input<br>     │          │           │<br>     └──────────┼───────────┘<br>                │<br>                ▼<br>         Scheduling queues<br>                │<br>                ▼<br>           Event Loop<br>                │<br>                ▼<br>          Call Stack<br>                │<br>                ▼<br>           JavaScript</pre><p>This diagram is simplified.</p><p>The real browser architecture is more complicated, and different browser engines implement things differently.</p><p>But it gives you the right mental model:</p><p><strong>JavaScript execution is only one part of the system.</strong></p><h3>And this is why timers don’t “run JavaScript in the background”</h3><p>Consider:</p><pre>setTimeout(() =&gt; {<br>  console.log(&quot;Done&quot;);<br>}, 1000);</pre><p>A common mental model is:</p><blockquote><strong>“JavaScript starts a timer thread that waits one second.”</strong></blockquote><p>That’s not a good way to think about it.</p><p>The browser provides the timer functionality.</p><p>After the timer’s delay has elapsed, the callback becomes eligible to be scheduled.</p><p>Then JavaScript executes the callback when the main thread is available.</p><p>So this:</p><pre>setTimeout(() =&gt; {<br>  console.log(&quot;Done&quot;);<br>}, 1000);<br><br>while (true) {}</pre><p>is a terrible idea.</p><p>Why?</p><p>Because the timer can become ready, but the JavaScript thread is still stuck inside the infinite loop.</p><p>The callback cannot simply interrupt the currently executing JavaScript.</p><p>The browser can know:</p><blockquote><strong>“The timer is ready.”</strong></blockquote><p>But JavaScript still has to get a chance to run:</p><pre>Main JavaScript thread<br><br>while (true) {<br>   // never finishes<br>}<br>        ↓<br>Timer becomes ready<br>        ↓<br>Callback waits<br>        ↓<br>JavaScript never becomes available</pre><p>This is one of the most important distinctions to understand.</p><p><strong>Asynchronous does not mean JavaScript is executing your callback on another thread.</strong></p><h3>So why doesn’t the UI freeze all the time?</h3><p>Because the browser is doing much more than executing JavaScript.</p><p>But there is an important catch.</p><p>The main thread is often responsible for work that directly affects your page’s responsiveness, including JavaScript execution and parts of the rendering process.</p><p>That means this can still freeze the page:</p><pre>const start = performance.now();<br><br>while (performance.now() - start &lt; 5000) {<br>  // expensive work<br>}</pre><p>For five seconds, JavaScript keeps the main thread busy.</p><p>During that time, interactions and rendering work that need the main thread can be delayed.</p><p>And this is where the phrase:</p><blockquote><strong>“JavaScript is single-threaded”</strong></blockquote><p>starts to matter.</p><h3>The browser can be multithreaded while your JavaScript isn’t</h3><p>This is the key distinction.</p><p>A browser process can use multiple threads for different kinds of work.</p><p>The exact architecture varies between browsers and operating systems, but modern browsers are highly concurrent internally.</p><p>You might have work happening around:</p><pre>Browser<br>│<br>├── JavaScript execution<br>├── Network activity<br>├── Rendering-related work<br>├── Image/media processing<br>├── Browser services<br>└── Other internal tasks</pre><p>But that does <strong>not</strong> mean you can write:</p><pre>runThisFunctionOnAnotherBrowserThread();</pre><p>for arbitrary JavaScript.</p><p>Your normal JavaScript execution still follows its single-threaded execution model.</p><p>If you want JavaScript itself to perform CPU-heavy work away from the main thread, that’s where <strong>Web Workers</strong> become useful.</p><h3>Conclusion</h3><p>JavaScript is single-threaded, but that doesn’t mean the entire browser is limited to one thread.</p><p>Your JavaScript runs on a main execution thread, while the browser handles many other responsibilities through its own internal systems.</p><p>Network requests, timers, user input, rendering, media processing, and other operations can happen outside the direct execution of your JavaScript code.</p><p>When those operations are ready to continue, the browser schedules the relevant callbacks or promise continuations so JavaScript can process them.</p><p>The main thread still matters, though.</p><p>If your JavaScript performs expensive work for too long, it can delay user interactions, rendering, and other tasks that depend on that thread.</p><p>So the browser can be highly concurrent while your JavaScript remains single-threaded.</p><p>That distinction explains both the power and the limitations of browser-based JavaScript.</p><h3>Takeaway</h3><p>Remember these three ideas:</p><ol><li><strong>JavaScript is single-threaded.</strong><br>Your normal JavaScript code runs one piece at a time on the main execution thread.</li><li><strong>The browser is a larger, concurrent system.</strong><br>It handles networking, timers, rendering, input, media, and other work beyond JavaScript execution.</li><li><strong>Asynchronous does not mean your callback runs on another thread.</strong><br>The browser handles the waiting, then schedules your JavaScript to run when the main thread is available.</li></ol><p>A useful mental model is:</p><pre>Browser<br>│<br>├── JavaScript execution<br>├── Network activity<br>├── Timers<br>├── User input<br>├── Rendering<br>├── Media processing<br>└── Other browser systems</pre><p>JavaScript is one part of that system — not the whole thing.</p><p>Once you understand that, the event loop, asynchronous APIs, UI freezing, and browser concurrency become much easier to reason about.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=26753988c06e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Your UI Changed. So Why Didn’t the Browser Paint It?]]></title>
            <link>https://medium.com/@developer.ad07/your-ui-changed-so-why-didnt-the-browser-paint-it-66d72c077e43?source=rss-a353cab2e24f------2</link>
            <guid isPermaLink="false">https://medium.com/p/66d72c077e43</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Aditya Dutta]]></dc:creator>
            <pubDate>Wed, 02 Sep 2026 07:30:10 GMT</pubDate>
            <atom:updated>2026-09-02T07:30:10.470Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aoULS-9plCe0jw5ntgoAOA.png" /></figure><p><em>You changed the DOM. Your JavaScript ran. So why did the user see nothing until much later?</em></p><p>There’s a frontend bug that can make you question everything you know about JavaScript.</p><p>You click a button.</p><p>You change the text on the screen.</p><p>You show a loading spinner.</p><p>Then you start some expensive JavaScript work.</p><p>You expect this:</p><pre>Click<br>  ↓<br>&quot;Loading...&quot;<br>  ↓<br>Heavy work<br>  ↓<br>&quot;Done!&quot;</pre><p>But the browser sometimes gives you this:</p><pre>Click<br>  ↓<br>Heavy JavaScript<br>  ↓<br>&quot;Done!&quot;</pre><p>The &quot;Loading...&quot; state never appeared.</p><p>Not because your JavaScript failed.</p><p>Not because the DOM didn’t change.</p><p>The DOM changed.</p><p><strong>The browser simply didn’t get a chance to show you the change.</strong></p><p>That distinction completely changed the way I think about frontend performance.</p><h3>The DOM can change before the user sees the change</h3><p>Consider this simple example:</p><pre>button.addEventListener(&quot;click&quot;, () =&gt; {<br>  status.textContent = &quot;Loading...&quot;;<br>  doSomethingExpensive();<br>  status.textContent = &quot;Done!&quot;;<br>});</pre><p>At first glance, nothing looks wrong.</p><p>The browser executes:</p><ol><li>Change the text to &quot;Loading...&quot;</li><li>Run expensive JavaScript</li><li>Change the text to &quot;Done!&quot;</li></ol><p>So you might expect the user to briefly see &quot;Loading...&quot;.</p><p>But that’s not necessarily what happens.</p><p>The browser’s main thread is responsible for running most JavaScript as well as handling events and rendering work such as style, layout, and painting. A long-running JavaScript task can therefore delay the browser’s opportunity to update what the user sees.</p><p>That’s the part that feels strange at first.</p><p><strong>Changing the DOM is not the same thing as painting pixels to the screen.</strong></p><p>And once you understand that, a lot of “weird” frontend behavior suddenly makes sense.</p><h3>The practical takeaway</h3><p>When debugging UI responsiveness, don’t ask only:</p><blockquote>“Did my state or DOM update?”</blockquote><p>Also ask:</p><blockquote><strong>“When did the browser actually get a chance to render that update?”</strong></blockquote><h3>The browser has another job besides running your JavaScript</h3><p>It’s easy to imagine the browser as something that simply executes our code.</p><p>We write:</p><pre>element.textContent = &quot;Hello&quot;;</pre><p>and imagine the browser immediately drawing &quot;Hello&quot;.</p><p>But the browser has a lot more to do.</p><p>The main thread may need to:</p><ul><li>process user input</li><li>execute JavaScript</li><li>calculate styles</li><li>calculate layout</li><li>paint pixels</li><li>handle other browser work</li><li>respond to the next interaction</li></ul><p>And most of that work is competing for the same main-thread time.</p><p>The browser’s event loop processes JavaScript tasks and microtasks, then can perform needed rendering before moving on. If your JavaScript keeps the main thread busy, the rendering opportunity can be delayed.</p><p>Think of the main thread as one person working at a very busy desk.</p><p>You keep handing them jobs:</p><blockquote>“Run this function.”</blockquote><blockquote>“Handle this click.”</blockquote><blockquote>“Calculate this.”</blockquote><blockquote>“Process this array.”</blockquote><blockquote>“Update the UI.”</blockquote><blockquote>“Paint the screen.”</blockquote><p>They don’t have infinite hands.</p><p>If you give them one enormous JavaScript task, everything else has to wait.</p><h3>This is where the “16ms” idea becomes interesting</h3><p>You’ve probably heard frontend developers talk about the <strong>16.67ms frame budget</strong>.</p><p>It can sound like one of those performance numbers developers memorize because they’re supposed to.</p><p>But it’s easier to understand if you think about what the browser has to accomplish between frames.</p><p>At 60Hz, a new frame is available roughly every 16.7ms.</p><p>That time isn’t reserved exclusively for your JavaScript.</p><p>The browser also needs time for things such as scripting, style calculation, layout, and painting.</p><p>So imagine you have:</p><pre>16.67ms<br>────────────────────────────<br>JavaScript       ██████████<br>Style            ██<br>Layout           ██<br>Paint            ██<br>────────────────────────────</pre><p>Now imagine your JavaScript takes much longer:</p><pre>16.67ms<br>────────────────────────────<br>JavaScript       ███████████████████████████<br>Style<br>Layout<br>Paint<br>────────────────────────────</pre><p>The browser doesn’t magically create another 20 milliseconds.</p><p>Your frame is late.</p><p>And when frames keep arriving late, users experience things like:</p><ul><li>laggy scrolling</li><li>delayed buttons</li><li>frozen loading states</li><li>stuttering animations</li><li>input lag</li><li>interfaces that feel “heavy”</li></ul><h3>The practical takeaway</h3><p><strong>Frontend performance isn’t only about making JavaScript execute faster.</strong></p><p>It’s also about making sure the browser gets enough opportunities to do everything else.</p><h3>The sneaky part: splitting functions doesn’t necessarily help</h3><p>Here’s a mistake that looks like optimisation:</p><pre>function updateEverything() {<br>  updateHeader();<br>  updateSidebar();<br>  processProducts();<br>  calculateTotals();<br>  updateCharts();<br>}</pre><p>You might think the work is now divided into smaller pieces because each operation has its own function.</p><p>But all of those functions still run synchronously as part of the same task:</p><pre>button.addEventListener(&quot;click&quot;, () =&gt; {<br>  status.textContent = &quot;Loading...&quot;;<br>  updateEverything();<br>  status.textContent = &quot;Done&quot;;<br>});</pre><p>The browser cannot usually paint the &quot;Loading...&quot; state until the click handler and all of the work inside updateEverything() have finished.</p><p>The same thing happens if you write the calls separately:</p><pre>button.addEventListener(&quot;click&quot;, () =&gt; {<br>  status.textContent = &quot;Loading...&quot;;<br>  updateHeader();<br>  updateSidebar();<br>  processProducts();<br>  calculateTotals();<br>  updateCharts();<br>  status.textContent = &quot;Done&quot;;<br>});</pre><p>The functions are smaller from a code-organisation perspective.</p><p><strong>The browser task is not smaller.</strong></p><p>To create separate opportunities for the browser to respond, you need to yield between chunks of work:</p><pre>async function updateEverything() {<br>  updateHeader();<br>  updateSidebar();<br>  await new Promise(resolve =&gt; setTimeout(resolve, 0));<br>    processProducts();<br>    calculateTotals();<br>    await new Promise(resolve =&gt; setTimeout(resolve, 0));<br>    updateCharts();<br>}<br><br><br>button.addEventListener(&quot;click&quot;, async () =&gt; {<br>  status.textContent = &quot;Loading...&quot;;<br>  await updateEverything();<br>  status.textContent = &quot;Done&quot;;<br>});</pre><p>Now the browser can handle pending work between chunks, including rendering the loading state.</p><p>This is an important distinction.</p><p><strong>Breaking code into functions is good for organisation. It doesn’t automatically break a long task into multiple browser opportunities.</strong></p><p>A long task is generally defined as an uninterrupted main-thread task lasting more than 50ms. During such work, user interactions and visual updates can be delayed.</p><h3>Give the browser a chance to breathe</h3><p>Suppose you have a large amount of work that genuinely needs to happen.</p><p>Instead of doing everything in one uninterrupted task:</p><pre>function processEverything(items) {<br>  for (const item of items) {<br>    expensiveCalculation(item);<br>  }<br>}</pre><p>you can split the work into smaller chunks.</p><p>Conceptually:</p><pre>async function processItems(items) {<br>  for (const chunk of chunks(items)) {<br>    processChunk(chunk);<br>    await new Promise(resolve =&gt; {<br>      setTimeout(resolve, 0);<br>    });<br>  }<br>}</pre><p>Now the browser has opportunities between chunks to handle other work, including UI updates.</p><p>Modern browsers also expose scheduler.yield() for yielding from long-running work where supported. It is specifically designed to let the browser handle higher-priority work before your JavaScript continues.</p><p>The exact scheduling strategy depends on the problem.</p><p>The important idea is simpler:</p><blockquote><strong>Don’t make the browser wait for your entire workload before giving it another opportunity to respond.</strong></blockquote><h3>This explains a UI bug I’ve seen over and over</h3><p>Imagine a search interface.</p><p>The user selects a filter.</p><p>You immediately want to show:</p><pre>Filtering...</pre><p>Then you process 50,000 records.</p><p>A naive implementation might look like:</p><pre>filterButton.addEventListener(&quot;click&quot;, () =&gt; {<br>  status.textContent = &quot;Filtering...&quot;;<br>  const results = expensiveFilter(allProducts);<br>  renderResults(results);<br>  status.textContent = &quot;Done&quot;;<br>});</pre><p>The code looks completely reasonable.</p><p>But if expensiveFilter() takes long enough, the user might never see &quot;Filtering...&quot;.</p><p>The interface feels broken.</p><p>The developer might start investigating:</p><blockquote>“Why isn’t React updating?”</blockquote><blockquote>“Is my state wrong?”</blockquote><blockquote>“Is the browser caching something?”</blockquote><blockquote>“Is CSS hiding the element?”</blockquote><p>Sometimes the real problem is much simpler:</p><p><strong>The main thread was busy.</strong></p><p>The browser couldn’t paint the intermediate state when you expected it to.</p><h3>A better mental model</h3><p>Think of UI updates as having two stages:</p><pre>Your JavaScript<br>      ↓<br>Changes state / DOM<br>      ↓<br>Browser gets an opportunity<br>      ↓<br>Style / Layout / Paint<br>      ↓<br>User sees pixels</pre><p>There is a gap between the first and the last step.</p><p>That gap matters.</p><h3>React doesn’t escape this problem</h3><p>This isn’t a “vanilla JavaScript problem.”</p><p>React can make state management easier, but your application still ultimately has to run JavaScript and interact with the browser’s rendering environment.</p><p>You can write:</p><pre>setLoading(true);<br>doSomethingVeryExpensive();<br>setLoading(false);</pre><p>and still have the same fundamental problem.</p><p>The important question isn’t:</p><blockquote>“Did I call setLoading(true)?&quot;</blockquote><p>It’s:</p><blockquote><strong>“Did the browser get an opportunity to render that state before the expensive work continued?”</strong></blockquote><p>That’s a much more useful way to think about performance in React applications.</p><p>The same mental model applies to:</p><ul><li>Next.js applications</li><li>dashboards</li><li>data-heavy tables</li><li>client-side filtering</li><li>large lists</li><li>complex animations</li><li>expensive calculations</li><li>drag-and-drop interfaces</li></ul><p>The framework changes.</p><p>The browser still has a main thread.</p><h3>Sometimes the best solution is to stop doing the work there</h3><p>There are cases where breaking work into smaller chunks isn’t enough.</p><p>Maybe you’re processing a huge dataset.</p><p>Maybe you’re doing image manipulation.</p><p>Maybe you’re calculating something computationally expensive.</p><p>In those cases, a <strong>Web Worker</strong> can move JavaScript computation to another thread, keeping the main thread available for UI work. Workers can’t directly manipulate the DOM, but they can perform computation and communicate results back to the main thread.</p><p>The architecture becomes something like:</p><pre>┌──────────────────┐<br>                 │   Main Thread    │<br>                 │                  │<br>User Input ────→ │ UI + DOM + Paint │<br>                 └────────┬─────────┘<br>                          │<br>                          │ data<br>                          ↓<br>                 ┌──────────────────┐<br>                 │   Web Worker     │<br>                 │                  │<br>                 │ Heavy computation│<br>                 └──────────────────┘</pre><p>Now your expensive calculation doesn’t have to monopolize the same thread responsible for keeping the interface responsive.</p><h3>The DevTools trick I wish more frontend developers used</h3><p>When an interface feels slow, don’t immediately start rewriting code.</p><p>Open Chrome DevTools.</p><p>Record a Performance trace.</p><p>Then look at the <strong>Main</strong> thread.</p><p>You’re looking for something like:</p><pre>Main<br>██████████████████████████████<br>       Long JavaScript task<br>                             █<br>                             Paint</pre><p>Instead of:</p><pre>Main<br>████ JavaScript<br>    ██ Render<br>       ███ JavaScript<br>           ██ Render<br>              █ JavaScript</pre><p>The second pattern gives the browser more opportunities to respond.</p><p>Long tasks are particularly important because they can cause delayed input, sluggish animations, and delayed visual updates.</p><p>This is one of those cases where the performance timeline is often more useful than staring at the source code.</p><h3>The practical takeaway</h3><p>When a UI “feels slow,” measure <strong>what the main thread is doing</strong>, not just how many lines of JavaScript you have.</p><h3>The biggest misconception I had about frontend performance</h3><p>It’s tempting to think:</p><blockquote><strong>Fast JavaScript = fast website.</strong></blockquote><p>It’s not that simple.</p><p>A better mental model is:</p><blockquote><strong>Fast JavaScript is useful. Available main-thread time is even more important.</strong></blockquote><p>A function that takes 5ms might be perfectly fine.</p><p>A function that takes 200ms might be a serious problem.</p><p>But even that isn’t the whole story.</p><p>What matters is <strong>when the work happens, what it competes with, and whether the browser gets opportunities to respond to the user.</strong></p><p>That’s why two applications can perform very differently even when their JavaScript does roughly the same amount of work.</p><h3>One idea worth remembering</h3><p>The next time you write:</p><pre>updateUI();<br>doSomethingExpensive();</pre><p>don’t just ask whether updateUI() ran.</p><p>Ask:</p><blockquote><strong>“Does the browser have a chance to paint this before I start the expensive work?”</strong></blockquote><p>That one question can lead you to an entirely different debugging path.</p><p>Because the browser doesn’t paint every time you change the DOM.</p><p>It paints when it gets an opportunity to render.</p><p>And your JavaScript can take that opportunity away.</p><h3>The browser isn’t ignoring your UI</h3><p>When your UI doesn’t appear immediately, it can feel like something went wrong.</p><p>Sometimes nothing is wrong with the UI code.</p><p>The browser is simply busy.</p><p>Your JavaScript, event handlers, rendering work, layout calculations, and other tasks are all competing for time on a very busy main thread.</p><p>So here’s the mental model I’d keep:</p><pre>JavaScript changes the UI<br>          ↓<br>The browser still has work to do<br>          ↓<br>The main thread must become available<br>          ↓<br>Rendering gets an opportunity<br>          ↓<br>The user finally sees the change</pre><p><strong>Your code changing the UI and the user seeing the UI are two different events.</strong></p><p>Once you really understand that, “the UI didn’t update” stops being a mysterious frontend bug.</p><p>It becomes a performance problem you can reason about.</p><p>And the next time you build a loading state, animation, search filter, or expensive interaction, don’t just make the JavaScript work.</p><p><strong>Leave the browser enough room to show the user that your work is happening.</strong></p><p>That small shift in thinking can make a surprisingly big difference.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=66d72c077e43" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>