<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Parth</title>
    <description>The latest articles on DEV Community by Parth (@parthctrl).</description>
    <link>https://dev.to/parthctrl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026306%2F046cb9f7-8fba-40a0-a536-b37f02853120.jpg</url>
      <title>DEV Community: Parth</title>
      <link>https://dev.to/parthctrl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parthctrl"/>
    <language>en</language>
    <item>
      <title>How does a string have methods if it's not an object?</title>
      <dc:creator>Parth</dc:creator>
      <pubDate>Fri, 23 Oct 2026 17:44:15 +0000</pubDate>
      <link>https://dev.to/parthctrl/how-does-a-string-have-methods-if-its-not-an-object-d0e</link>
      <guid>https://dev.to/parthctrl/how-does-a-string-have-methods-if-its-not-an-object-d0e</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the fifth post in a series I'm writing as I learn JavaScript.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By now this series has a running theme: I learn a rule, then I find something that seems to break it, and chasing down &lt;em&gt;why&lt;/em&gt; teaches me more than the rule did.&lt;/p&gt;

&lt;p&gt;Here's this one.&lt;/p&gt;

&lt;p&gt;I'd just learned that strings are &lt;strong&gt;primitives&lt;/strong&gt;. Not objects — primitives. A string is a single value, like a number or a boolean. Fine.&lt;/p&gt;

&lt;p&gt;Then, on the same day, I wrote this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "PARTH"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And stopped.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.toUpperCase()&lt;/code&gt; is a &lt;strong&gt;method&lt;/strong&gt;. &lt;code&gt;.length&lt;/code&gt; is a &lt;strong&gt;property&lt;/strong&gt;. Those belong to &lt;em&gt;objects&lt;/em&gt;. But I was just told a string is a primitive, not an object. So how does a primitive have methods hanging off it?&lt;/p&gt;

&lt;p&gt;Either strings are secretly objects, or something sneaky is happening. It turns out to be the second one, and it has a name: &lt;strong&gt;autoboxing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, strings really are primitives
&lt;/h2&gt;

&lt;p&gt;Just to be sure I hadn't misunderstood:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "string", not "object"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A normal string is a primitive. It's not an object. That part was true.&lt;/p&gt;

&lt;p&gt;So the methods aren't &lt;em&gt;on&lt;/em&gt; the string. The string is borrowing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happens: autoboxing
&lt;/h2&gt;

&lt;p&gt;When you write &lt;code&gt;name.toUpperCase()&lt;/code&gt;, JavaScript does something behind your back, in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It sees you trying to use a method on a primitive.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;temporarily wraps&lt;/strong&gt; the primitive in its matching object — here, a &lt;code&gt;String&lt;/code&gt; object. (Numbers get a &lt;code&gt;Number&lt;/code&gt; object, booleans a &lt;code&gt;Boolean&lt;/code&gt;, and so on.)&lt;/li&gt;
&lt;li&gt;The object &lt;em&gt;does&lt;/em&gt; have all the methods, so &lt;code&gt;.toUpperCase()&lt;/code&gt; runs.&lt;/li&gt;
&lt;li&gt;You get your result back.&lt;/li&gt;
&lt;li&gt;The temporary wrapper object is &lt;strong&gt;thrown away&lt;/strong&gt;.
That wrap-use-discard move is &lt;strong&gt;autoboxing&lt;/strong&gt;. The primitive stays a primitive. For a split second, JavaScript loans it an object body so it can use the methods, then takes the body back the instant it's done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You never see the wrapper. It's created and destroyed inside that one expression.&lt;/p&gt;

&lt;p&gt;So the string didn't have methods. JavaScript briefly lent it some.&lt;/p&gt;

&lt;h2&gt;
  
  
  The object version actually exists
&lt;/h2&gt;

&lt;p&gt;The wrapper JavaScript creates temporarily is a real thing you can make yourself, on purpose, with &lt;code&gt;new String()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// primitive string&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// String OBJECT&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "string"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "object"  ← different!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;b&lt;/code&gt; is the object version — the same kind of object autoboxing creates for a moment, except this one sticks around because you asked for it.&lt;/p&gt;

&lt;p&gt;You can confirm it's a real object instance with &lt;code&gt;instanceof&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true  — b was built from the String constructor&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false — a is a primitive, not an instance of anything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(An &lt;strong&gt;instance&lt;/strong&gt; is just an object created from a constructor or class — &lt;code&gt;new String("parth")&lt;/code&gt; creates an instance of &lt;code&gt;String&lt;/code&gt;, the same way &lt;code&gt;new Date()&lt;/code&gt; creates an instance of &lt;code&gt;Date&lt;/code&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  You almost never want the object version
&lt;/h2&gt;

&lt;p&gt;Here's the catch, and the reason I'm glad I learned this rather than just using &lt;code&gt;new String()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They look identical, but one's a primitive and one's an object, so strict equality says no. Object wrappers also behave strangely in conditionals and comparisons. The rule that falls out of this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Always write string primitives — &lt;code&gt;"parth"&lt;/code&gt;, not &lt;code&gt;new String("parth")&lt;/code&gt;.&lt;/strong&gt; Let autoboxing hand you the methods when you need them. You get all the convenience of the object with none of the weirdness.&lt;/p&gt;

&lt;p&gt;The object wrapper isn't something you're meant to create. It's machinery JavaScript uses internally, and it just happens to be reachable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took away
&lt;/h2&gt;

&lt;p&gt;For a while I thought JavaScript was being contradictory: &lt;em&gt;strings are primitives, but also they have methods like objects do.&lt;/em&gt; Both can't be true.&lt;/p&gt;

&lt;p&gt;They are both true — because of timing. The string is a primitive at rest. It only becomes object-shaped for the instant you call a method, then snaps back. Autoboxing is the bridge between "simple value" and "has useful methods," and it's invisible precisely because it cleans up after itself.&lt;/p&gt;

&lt;p&gt;It's the same lesson as the rest of this series, really: the weird behavior isn't JavaScript being careless. It's a mechanism doing something deliberate, just quietly. Once you can see it, it stops being a contradiction and starts being a feature.&lt;/p&gt;




&lt;p&gt;That's where this little series lands for now — five "wait, what?" moments from my first notebook of JavaScript, each one explained instead of memorized. If you've hit one I haven't covered, drop it in the comments. It might be the next post.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Copy or reference? Stack, heap, and why changing one thing changed two</title>
      <dc:creator>Parth</dc:creator>
      <pubDate>Tue, 20 Oct 2026 10:15:37 +0000</pubDate>
      <link>https://dev.to/parthctrl/copy-or-reference-stack-heap-and-why-changing-one-thing-changed-two-2ke2</link>
      <guid>https://dev.to/parthctrl/copy-or-reference-stack-heap-and-why-changing-one-thing-changed-two-2ke2</guid>
      <description>&lt;p&gt;Here's the moment JavaScript stopped making sense to me for an afternoon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10 — fine, a didn't change&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Makes sense. &lt;code&gt;b&lt;/code&gt; got its own copy of &lt;code&gt;10&lt;/code&gt;, I changed &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt; stayed put. Exactly what you'd expect.&lt;/p&gt;

&lt;p&gt;Then I did what looked like the same thing with an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vatsal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Vatsal" — wait, WHAT?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I changed &lt;code&gt;person2&lt;/code&gt;. But &lt;code&gt;person1&lt;/code&gt; changed too. I never touched &lt;code&gt;person1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Same pattern, completely different result. Figuring out why taught me one of the most important ideas in the language: &lt;strong&gt;some values are copied, and some are shared.&lt;/strong&gt; Which one you get depends on the type — and it comes down to where JavaScript stores things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two kinds of data, two kinds of storage
&lt;/h2&gt;

&lt;p&gt;From an earlier post in this series: JavaScript has two families of types.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primitives&lt;/strong&gt; — string, number, boolean, null, undefined, bigint, symbol. A single value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-primitives&lt;/strong&gt; — objects, arrays, functions. Collections of values.
What I didn't know is that JavaScript keeps them in two different places in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The stack&lt;/strong&gt; is for primitives. It's small, fast, and orderly, and it holds the value &lt;em&gt;directly&lt;/em&gt;. When a variable holds a number, the number itself is sitting right there in the stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The heap&lt;/strong&gt; is for objects. Objects can be big and grow over time, so they live in a larger, more flexible space. But the variable doesn't hold the object itself — it holds a &lt;strong&gt;reference&lt;/strong&gt;: an address that points to where the object lives in the heap.&lt;/p&gt;

&lt;p&gt;That difference — value vs address — is the whole explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the number behaved
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;a&lt;/code&gt; holds &lt;code&gt;10&lt;/code&gt; directly in the stack. When you write &lt;code&gt;let b = a&lt;/code&gt;, JavaScript copies the &lt;strong&gt;value&lt;/strong&gt;. Now &lt;code&gt;b&lt;/code&gt; has its own &lt;code&gt;10&lt;/code&gt;, completely separate.&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt; has no idea. They were never connected — just two boxes that happened to hold the same number.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;copy by value&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the object didn't
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;person1&lt;/code&gt; doesn't hold the object. It holds a &lt;strong&gt;reference&lt;/strong&gt; — an address pointing to the object in the heap.&lt;/p&gt;

&lt;p&gt;When you write &lt;code&gt;let person2 = person1&lt;/code&gt;, JavaScript copies the &lt;strong&gt;reference&lt;/strong&gt;, not the object. So now &lt;code&gt;person1&lt;/code&gt; and &lt;code&gt;person2&lt;/code&gt; hold the &lt;em&gt;same address&lt;/em&gt;. Two variables, one object, pointing at the exact same thing in the heap.&lt;/p&gt;

&lt;p&gt;So when you do &lt;code&gt;person2.name = "Vatsal"&lt;/code&gt;, you follow the address to the one object and change it. And since &lt;code&gt;person1&lt;/code&gt; points to that same object, it sees the change too.&lt;/p&gt;

&lt;p&gt;You didn't have two objects. You had two signposts pointing at one.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;copy by reference&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental picture that made it click
&lt;/h2&gt;

&lt;p&gt;A primitive is like writing a phone number on two separate sticky notes. Change one note, the other is untouched — they were only ever copies.&lt;/p&gt;

&lt;p&gt;An object is like two sticky notes that both say &lt;em&gt;"the contact is in drawer 3."&lt;/em&gt; Go to drawer 3 and change the contact, and both notes now point to the changed thing. You didn't copy the contact. You copied the location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STACK (primitives, held directly)      HEAP (objects, held by reference)

 a  →  10                               person1 ──┐
 b  →  10   (its own copy)                         ├──→  { name: "Vatsal" }
                                        person2 ──┘    (one object, two pointers)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  This connects back to const
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;var&lt;/code&gt;/&lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; post, I mentioned a &lt;code&gt;const&lt;/code&gt; quirk that now makes complete sense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vatsal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// works fine&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Aryan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// TypeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;const&lt;/code&gt; locks the &lt;strong&gt;reference&lt;/strong&gt; — the address the variable holds. You can't point it at a &lt;em&gt;different&lt;/em&gt; object. But you can absolutely follow the existing address and change what's &lt;em&gt;inside&lt;/em&gt;. The box is glued in place; its contents aren't.&lt;/p&gt;

&lt;p&gt;Stack-vs-heap is why. &lt;code&gt;const&lt;/code&gt; protects what's in the variable (the address), not what's across the heap at the other end of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical catch
&lt;/h2&gt;

&lt;p&gt;This bites people in real code constantly. The classic version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;backup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// you THINK you saved a copy&lt;/span&gt;

&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 99 — your "backup" changed too&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;backup&lt;/code&gt; was never a copy. It's the same object. If you actually want a separate one, you have to make a real copy — for a shallow one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;backup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// spread into a brand new object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;backup&lt;/code&gt; points to its own object in the heap, and the two move independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took away
&lt;/h2&gt;

&lt;p&gt;I used to think "copy" meant one thing. It doesn't. In JavaScript, copying a primitive copies the value, and copying an object copies the &lt;em&gt;address&lt;/em&gt; — and those two behave in opposite ways the moment you change something.&lt;/p&gt;

&lt;p&gt;Once I pictured the stack holding values and the heap holding objects behind pointers, every one of these "wait, what?" moments turned into "oh, of course." The number stays independent because it was copied. The object moves together because it was shared.&lt;/p&gt;

&lt;p&gt;Same word, two behaviors. The type tells you which one you're getting.&lt;/p&gt;




&lt;p&gt;Did this one get you too? The &lt;code&gt;backup&lt;/code&gt; that wasn't actually a backup got me early on. I'd love to hear your version in the comments.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why "1" + 2 + 2 is "122" but 1 + 2 + "2" is "32"</title>
      <dc:creator>Parth</dc:creator>
      <pubDate>Sun, 11 Oct 2026 18:16:37 +0000</pubDate>
      <link>https://dev.to/parthctrl/why-1-2-2-is-122-but-1-2-2-is-32-5gj0</link>
      <guid>https://dev.to/parthctrl/why-1-2-2-is-122-but-1-2-2-is-32-5gj0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the third post in a series I'm writing as I learn JavaScript.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are two lines that look almost identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "122"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "32"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same numbers. Same &lt;code&gt;+&lt;/code&gt;. The only difference is &lt;em&gt;where&lt;/em&gt; the string sits. And yet the answers aren't just different — they're different &lt;em&gt;kinds&lt;/em&gt; of thing. One is a hundred and twenty-two-ish. The other is thirty-two-ish. Both are actually text.&lt;/p&gt;

&lt;p&gt;When I first saw this I assumed it was a trick question. It isn't. Once you know the two rules behind it, it's completely predictable — and it stops being a source of bugs.&lt;/p&gt;

&lt;p&gt;Here are the rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 1: JavaScript reads left to right
&lt;/h2&gt;

&lt;p&gt;JavaScript doesn't look at the whole line and plan ahead. It works through it one step at a time, left to right, and each &lt;code&gt;+&lt;/code&gt; is evaluated before moving to the next.&lt;/p&gt;

&lt;p&gt;So the line isn't judged all at once. It's a chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 2: &lt;code&gt;+&lt;/code&gt; has two completely different jobs
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;+&lt;/code&gt; operator does one of two things depending on what it's touching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two numbers → &lt;strong&gt;addition&lt;/strong&gt;. &lt;code&gt;2 + 2&lt;/code&gt; is &lt;code&gt;4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Anything involving a string → &lt;strong&gt;joining&lt;/strong&gt; (concatenation). &lt;code&gt;"a" + "b"&lt;/code&gt; is &lt;code&gt;"ab"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here's the key part: &lt;strong&gt;the moment &lt;code&gt;+&lt;/code&gt; touches a string, it converts the other side into a string too&lt;/strong&gt;, then glues them together. This automatic conversion has a name — &lt;strong&gt;type coercion&lt;/strong&gt;. JavaScript coerces one value into another type to make the operation work.&lt;/p&gt;

&lt;p&gt;Now let's walk through both lines with those two rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;"1" + 2 + 2&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Left to right:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"1" + 2     → "1" touches a string operation → 2 becomes "2" → "12"
"12" + 2    → still a string → 2 becomes "2" → "122"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;"122"&lt;/code&gt;. The string at the &lt;em&gt;front&lt;/em&gt; poisons the whole chain. Once step one produces a string, every step after it is also a string.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;1 + 2 + "2"&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Left to right:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 + 2       → two numbers → real addition → 3
3 + "2"     → now a string appears → 3 becomes "3" → "32"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: &lt;code&gt;"32"&lt;/code&gt;. Here the numbers get to add up &lt;em&gt;first&lt;/em&gt;, because the string doesn't show up until the end. &lt;code&gt;1 + 2&lt;/code&gt; becomes &lt;code&gt;3&lt;/code&gt;, and only then does the &lt;code&gt;"2"&lt;/code&gt; turn it into text.&lt;/p&gt;

&lt;p&gt;That's the whole mystery. Same pieces, different order, and left-to-right evaluation does the rest. The string acts like a switch: everything after it becomes text.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other operators aren't so confused
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;+&lt;/code&gt; is the troublemaker because it has two jobs. Every other math operator has only one — math — so they don't get tempted to join strings. Instead, they convert strings &lt;em&gt;into numbers&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 3   ("5" becomes 5)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 6  (both become numbers)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-&lt;/code&gt; can't join anything, so when it meets a string it does the only thing it knows: turn it into a number and subtract. Same for &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So there's a rough rule of thumb:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;+&lt;/code&gt; &lt;strong&gt;leans toward strings&lt;/strong&gt; — if it sees one, it joins.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt; &lt;strong&gt;lean toward numbers&lt;/strong&gt; — they always convert to number and do math.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When conversion fails: NaN
&lt;/h2&gt;

&lt;p&gt;If you ask JavaScript to turn something into a number and it can't, you don't get an error. You get &lt;strong&gt;NaN&lt;/strong&gt; — "Not a Number."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;"Parth"&lt;/code&gt; isn't a valid number, so the conversion fails, and NaN is the result. The strange part: NaN's &lt;em&gt;type&lt;/em&gt; is still &lt;code&gt;number&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a number-typed value that represents "this was supposed to be a number, but the math didn't work out." And you can't test for it with &lt;code&gt;===&lt;/code&gt;, because — famously — NaN isn't even equal to itself. You check for it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Two kinds of conversion
&lt;/h2&gt;

&lt;p&gt;Everything above is JavaScript converting types &lt;em&gt;on its own&lt;/em&gt;, mid-operation. That's called &lt;strong&gt;implicit conversion&lt;/strong&gt; (or type coercion) — the engine does it for you, whether you asked or not.&lt;/p&gt;

&lt;p&gt;You can also convert &lt;strong&gt;explicitly&lt;/strong&gt; — on purpose, in your own code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;25&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;           &lt;span class="c1"&gt;// a string&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;realAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// you convert it yourself&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;realAge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// 25&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;realAge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implicit is JavaScript deciding for you. Explicit is you deciding for JavaScript. Bugs tend to come from the first kind — the conversions you didn't realize were happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that bites everyone: == vs ===
&lt;/h2&gt;

&lt;p&gt;This is the most important practical takeaway, and it comes straight out of coercion.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;==&lt;/code&gt; compares values &lt;strong&gt;after&lt;/strong&gt; coercing them to the same type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true — "2" is coerced to 2 first&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;===&lt;/code&gt; compares values &lt;strong&gt;without&lt;/strong&gt; any coercion. Different type means not equal, full stop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false — number vs string, done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;==&lt;/code&gt; is doing the same silent conversion that produced &lt;code&gt;"122"&lt;/code&gt; — and that's exactly why it causes bugs. It says two things are equal when they only &lt;em&gt;look&lt;/em&gt; equal after JavaScript quietly reshapes one of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;===&lt;/code&gt; by default.&lt;/strong&gt; It compares what's actually there, instead of what things turn into.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took away
&lt;/h2&gt;

&lt;p&gt;For a while I thought JavaScript was just being weird on purpose. It isn't. Every one of these results comes from two simple rules — left to right, and &lt;code&gt;+&lt;/code&gt; prefers strings — plus the fact that the language would rather convert a type than throw an error.&lt;/p&gt;

&lt;p&gt;That last habit is the real theme. JavaScript almost never refuses. Give it a string where it wanted a number and it'll convert, join, or hand back NaN — anything but stop. That's convenient right up until it produces &lt;code&gt;"122"&lt;/code&gt; when you wanted &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can't turn the behavior off. But once you can see it coming, it stops being magic and starts being rules. And &lt;code&gt;===&lt;/code&gt; quietly shuts down a whole category of it.&lt;/p&gt;




&lt;p&gt;What's the coercion result that surprised you most? Mine was &lt;code&gt;typeof NaN&lt;/code&gt; being &lt;code&gt;"number"&lt;/code&gt;. I'd love to hear yours in the comments.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>var, let, const — and why JavaScript changed its mind</title>
      <dc:creator>Parth</dc:creator>
      <pubDate>Sat, 01 Aug 2026 19:16:19 +0000</pubDate>
      <link>https://dev.to/parthctrl/var-let-const-and-why-javascript-changed-its-mind-5f2o</link>
      <guid>https://dev.to/parthctrl/var-let-const-and-why-javascript-changed-its-mind-5f2o</guid>
      <description>&lt;p&gt;When I started learning JavaScript, I kept seeing the same advice: &lt;em&gt;use &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;, don't use &lt;code&gt;var&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Usually it came as a rule, not a reason. And a rule you don't understand is a rule you forget — so I went looking for the &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It turns out &lt;code&gt;var&lt;/code&gt; isn't just old-fashioned. It's broken in three specific ways, and &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; exist to fix exactly those three things.&lt;/p&gt;

&lt;p&gt;Here they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: var lets you redeclare the same variable
&lt;/h2&gt;

&lt;p&gt;Watch this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saini&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Saini"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No error. No warning. JavaScript just quietly lets you declare the same variable twice.&lt;/p&gt;

&lt;p&gt;That sounds harmless in a five-line example. Now imagine a 500-line file where you declare &lt;code&gt;var count&lt;/code&gt; at the top, and 300 lines later — having forgotten — you declare &lt;code&gt;var count&lt;/code&gt; again. Your original value is gone, and nothing tells you.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; refuses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saini&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// SyntaxError: Identifier 'name' has already been declared&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error &lt;em&gt;is the feature&lt;/em&gt;. It catches the mistake at the moment you make it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 2: var ignores blocks
&lt;/h2&gt;

&lt;p&gt;A block is anything inside curly braces — an &lt;code&gt;if&lt;/code&gt;, a &lt;code&gt;for&lt;/code&gt;, a bare &lt;code&gt;{ }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You'd expect a variable declared inside a block to stay inside it. &lt;code&gt;var&lt;/code&gt; doesn't care:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 21 — it escaped!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That variable leaked out of the &lt;code&gt;if&lt;/code&gt; and into the surrounding code. &lt;code&gt;var&lt;/code&gt; is &lt;strong&gt;function-scoped&lt;/strong&gt;, not block-scoped: it only respects the boundaries of a function, and treats &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt; blocks as if the braces weren't there.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are &lt;strong&gt;block-scoped&lt;/strong&gt;. They stay where you put them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Delhi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Delhi" — fine&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: city is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That error is the whole point. The variable did its job inside the block and then stopped existing, which is exactly what you wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 3: var gets quietly moved to the top
&lt;/h2&gt;

&lt;p&gt;This one broke my brain for a while:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined — not an error!&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used a variable &lt;em&gt;before I declared it&lt;/em&gt;, and JavaScript didn't complain. It printed &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The reason is &lt;strong&gt;hoisting&lt;/strong&gt;. Before running your code, JavaScript scans it and moves all &lt;code&gt;var&lt;/code&gt; declarations to the top of their scope. So what actually runs is closer to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;           &lt;span class="c1"&gt;// moved up, no value yet&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// the assignment stays put&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;declaration&lt;/em&gt; moves. The &lt;em&gt;value&lt;/em&gt; doesn't. So you get a variable that exists but is empty — and &lt;code&gt;undefined&lt;/code&gt; instead of a helpful error.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are hoisted too, but they refuse to be touched before their declaration line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: Cannot access 'b' before initialization&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again: &lt;strong&gt;the error is the improvement.&lt;/strong&gt; "Cannot access before initialization" tells you exactly what you did wrong. &lt;code&gt;undefined&lt;/code&gt; tells you nothing, and lets a broken program keep running.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's the difference between let and const?
&lt;/h2&gt;

&lt;p&gt;Simple version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;let&lt;/code&gt;&lt;/strong&gt; — the value can be changed later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;const&lt;/code&gt;&lt;/strong&gt; — the value cannot be reassigned after you create it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// fine&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vatsal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// TypeError: Assignment to constant variable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here's the part that trips people up. &lt;code&gt;const&lt;/code&gt; locks the &lt;strong&gt;variable&lt;/strong&gt;, not the &lt;strong&gt;contents&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vatsal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// this works!&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// { name: "Vatsal" }&lt;/span&gt;

&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Aryan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// this doesn't — TypeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can change what's &lt;em&gt;inside&lt;/em&gt; the object. You just can't point the variable at a &lt;em&gt;different&lt;/em&gt; object.&lt;/p&gt;

&lt;p&gt;Think of &lt;code&gt;const&lt;/code&gt; as gluing a label to a box. You can't move the label to another box — but you can still open the box and rearrange what's inside.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bonus problem: variables you never meant to create
&lt;/h2&gt;

&lt;p&gt;There's a fourth way to make a variable, and it's an accident:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// no let, no const, no var&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works. JavaScript silently creates a &lt;strong&gt;global&lt;/strong&gt; variable — one that's visible everywhere in your program. Misspell a variable name during an assignment and you don't get an error; you get a brand new global you didn't ask for, while the one you meant to update sits there unchanged.&lt;/p&gt;

&lt;p&gt;This is exactly what &lt;code&gt;"use strict"&lt;/code&gt; was made for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: name is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you still need to write it? Usually not — you're probably already in strict mode without knowing it. ES modules (anything with &lt;code&gt;import&lt;/code&gt;/&lt;code&gt;export&lt;/code&gt;) run in strict mode automatically, and so does most code in React, Next.js, Angular, and modern Node projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took away
&lt;/h2&gt;

&lt;p&gt;I came in expecting "&lt;code&gt;var&lt;/code&gt; is old, &lt;code&gt;let&lt;/code&gt; is new." That's not the story.&lt;/p&gt;

&lt;p&gt;The real story is that &lt;strong&gt;&lt;code&gt;var&lt;/code&gt; fails silently, and &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; fail loudly.&lt;/strong&gt; Redeclaring a variable, leaking one out of a block, using one before it exists — &lt;code&gt;var&lt;/code&gt; allows all three without a word. &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; throw an error at every one.&lt;/p&gt;

&lt;p&gt;That felt backwards to me at first. More errors sounds like a worse language.&lt;/p&gt;

&lt;p&gt;But an error at the moment you make a mistake is a gift. The alternative is &lt;code&gt;undefined&lt;/code&gt; quietly flowing through your program until it finally breaks somewhere far away — with no clue where it came from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;const&lt;/code&gt; by default. Use &lt;code&gt;let&lt;/code&gt; when the value genuinely needs to change. Reach for &lt;code&gt;var&lt;/code&gt; basically never.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And now you know why — not just that.&lt;/p&gt;




&lt;p&gt;What tripped you up most when you were learning scope? For me it was hoisting. I'd love to hear about it in the comments.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>typeof null is "object" — a bug from 1995 nobody can fix</title>
      <dc:creator>Parth</dc:creator>
      <pubDate>Sun, 12 Jul 2026 19:28:22 +0000</pubDate>
      <link>https://dev.to/parthctrl/typeof-null-is-object-a-bug-from-1995-nobody-can-fix-268g</link>
      <guid>https://dev.to/parthctrl/typeof-null-is-object-a-bug-from-1995-nobody-can-fix-268g</guid>
      <description>&lt;p&gt;I'm learning JavaScript. A few weeks in, I ran this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "object"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I stared at it for a while.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;null&lt;/code&gt; is not an object. It's the value you use to say &lt;em&gt;there is deliberately nothing here&lt;/em&gt;. It's a primitive — same family as &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;. So why does JavaScript insist on calling it an object?&lt;/p&gt;

&lt;p&gt;I assumed I'd misunderstood something. I hadn't. It's a bug. It's been in the language since 1995, everybody knows about it, and it is never getting fixed.&lt;/p&gt;

&lt;p&gt;Here's the story, because it turned out to be the most interesting thing I've learned so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it came from
&lt;/h2&gt;

&lt;p&gt;JavaScript was created by Brendan Eich in about 10 days in 1995. That's not a joke — Netscape wanted a scripting language for their browser and they wanted it immediately.&lt;/p&gt;

&lt;p&gt;When you build a language that fast, you take shortcuts. One of them was how values got stored in memory. Every value carried a small &lt;strong&gt;type tag&lt;/strong&gt; — a few bits at the front saying "this is a number," "this is a string," and so on. To find out a value's type, the engine just looked at the tag.&lt;/p&gt;

&lt;p&gt;The tag for an &lt;strong&gt;object&lt;/strong&gt; was all zeros.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;null&lt;/code&gt;? In that original implementation, &lt;code&gt;null&lt;/code&gt; was represented as a null pointer — which, on the machine, is also all zeros.&lt;/p&gt;

&lt;p&gt;So when &lt;code&gt;typeof&lt;/code&gt; looked at &lt;code&gt;null&lt;/code&gt;, it saw all zeros, checked its table, and confidently reported: &lt;strong&gt;object&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's it. That's the whole bug. Two different things happened to look identical to the one piece of code that was supposed to tell them apart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it was never fixed
&lt;/h2&gt;

&lt;p&gt;This is the part I find genuinely interesting.&lt;/p&gt;

&lt;p&gt;Everyone figured this out pretty quickly. It's not a mystery, and it's not hard to fix — you'd just special-case &lt;code&gt;null&lt;/code&gt; in &lt;code&gt;typeof&lt;/code&gt; and be done in an afternoon.&lt;/p&gt;

&lt;p&gt;But by the time anyone got around to it, the web already existed. Thousands of sites had shipped code that ran &lt;code&gt;typeof x === "object"&lt;/code&gt; and depended on getting &lt;code&gt;true&lt;/code&gt; back for &lt;code&gt;null&lt;/code&gt;. Some of that code was checking whether a value was "object-ish." Some of it was doing something weirder. Nobody knew exactly how much of it was out there, and nobody could go and edit it.&lt;/p&gt;

&lt;p&gt;So fixing the bug would mean breaking working websites. Real ones. Pages that people were using.&lt;/p&gt;

&lt;p&gt;There was actually a proposal, years later, to make &lt;code&gt;typeof null&lt;/code&gt; return &lt;code&gt;"null"&lt;/code&gt;. It was rejected. The reasoning was blunt: it would break too much.&lt;/p&gt;

&lt;p&gt;The bug stayed. Not because it was hard to fix, but because &lt;strong&gt;the cost of fixing it was higher than the cost of living with it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually took away from this
&lt;/h2&gt;

&lt;p&gt;I started out thinking this was a piece of JavaScript trivia — the kind of thing that shows up in interview questions and nowhere else.&lt;/p&gt;

&lt;p&gt;But it taught me something bigger, and it's not really about JavaScript:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once people depend on your mistake, it stops being a mistake and becomes a feature you have to support.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's a slightly uncomfortable thought when you're a beginner writing code nobody else will ever run. But it reframed how I read old, weird, "why is it like this" corners of a language. Usually the answer isn't that the designers were careless. It's that they were fast, or early, or working with constraints that no longer exist — and then the world built on top of them before anyone could go back.&lt;/p&gt;

&lt;p&gt;Ten days in 1995. One shortcut. And &lt;code&gt;typeof null === "object"&lt;/code&gt; ever since.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical bit
&lt;/h2&gt;

&lt;p&gt;If you actually need to check for &lt;code&gt;null&lt;/code&gt;, don't use &lt;code&gt;typeof&lt;/code&gt;. Just compare directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// definitely null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to know whether something is a real object, you have to rule &lt;code&gt;null&lt;/code&gt; out yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// an actual object&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That extra &lt;code&gt;value !== null&lt;/code&gt; is in a lot of real codebases. Now you know why it's there.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you ever come across a JavaScript behavior that made you stop and think, "Why does it work like that?" I'd love to hear about it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
