What is the actual difference between null and undefined ?

What is the actual difference between null and undefined ?

Disclaimer : The article is based on my skimming of the actual source code ,inconsistencies might be introduced due to missing overall context of the project and architecture .Take it on your own risk.


Whenever I am in an interview with this gentleman Karim EL MRISSANI and the question of the difference between null and undefined pops up ,we keep hearing those Instagram definitions and illustrations. I mean a standard definition would be enough in this case ,but since I am an internals guy and I like to build my understanding on what is actually on memory and how things work under the hood ,I will share the difference following my geeky style which reflects curiosity and deep understanding.

The standard definition of undefined is an implicit absence of value ,meaning that whenever we declare a variable without assigning a value (=) it is considered implicitly empty ,hence undefined. In the other hand, null also reflects an absence of value but an explicit one this time ,set by the programmer.

You might wonder why having two representations of “absence of value” , I would say it could be :

  • Design mistake since JS was created in a rush

  • Introduce compliance with other languages such as Java (adding null)

  • Keeping undefined for backward compatibility

Any other reason you might want to  add ?


Let me tell you now about the actual physical difference between null and undefined ,ready ?

The difference is the same as the difference between one and two .

What’s best than the source code itself to answer this. I’ve picked SpiderMonkey  engine (Mozilla JavaScript implementation) and skimmed its source code trying to find the answer .I ‘ve also checked other engines such as V8 (chrome engine) and it seems like they have some similarities especially on how representing values.

SpiderMonkey represents each JavaScript value as an instance of JS::Value which is a C++ class that can be found in Value class source.The class is well documented and further information can be found at SpiderMonkey internals.

The class seems to have only one unsinged 64 bit integer instance field and all the magic of any JavaScript value happens in this 64 bit .

The possible values In JavaScript are :

  • Number

  • Boolean true/false

  • Undefined

  • Null

  • Object

  • Symbol

  • String

  • BigInt

So basically this 64bit will represent all these values. By analyzing this 64 bit we need to be able to tell if we will have to perform a dereferencing (this 64 bit value is actually an address) which implies it is an object value ,Or we need to read the 64 bit as a raw value. The 64 bit is actually a tagged value which means it holds a tag in its bits which helps us perform the distinguishing .On 64 bit machines the tag is placed on the upper 17 bits of the 64 bit value and the other  47 is kept for the actual value (payload). 47 bit is more than enough to cover all the addresses a JavaScript app might use, but ! what if we are representing a huge number not an object , the number can require more than 47 bit, so where to put the tag ?

All numbers in JavaScript are encoded using the IEEE-754 double-precision (64-bit) floating-point format. This encoding is used by several other languages to represent floating numbers as you can’t place floating numbers as they are raw on a fixed memory  slot  as it is impossible to fit in the number and its floating part ,This is why we need some formula to encode numbers to make them fit in that slot .The formula is IEEE-754 double-precision which defines some NaN parts (it allocates some patterns to represent non numeric values ) .The formula says that if the exponent is all 1s it means that this value is NaN ,the exponent is the eleven upper bits after the sign bit.

The tag is the upper 17 bit , if we set the upper 12 bits to 1s (1 bit for sign, not important as we are making the value NaN + 11 bits of the exponent) we officially made the whole Value NaN and we have 5 remaining bits from 17 to perform distinguishing which is enough to represent other NaN types (null , undefined …)

Illustration of a asBits_ instance field

Now let’s discover the actual values of undefined Id and null Id .The class has a setUndefined /setNull methods which  are a good source for our search :

The code is self explanatory , but let’s dissect it a bit . setting a variable to undefined is actually left shifting the JSVAL_TAG_UNDEFINED by 47 which will move the tag to the upper 17 bits .

Now let’s compute JSVAL_TAG_UNDEFINED first :

JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED

JSVAL_TAG_MAX_DOUBLE = 0x1FFF0

JSVAL_TYPE_UNDEFINED = 0x03

JSVAL_TAG_UNDEFINED= 0x1FFF0 | 0x03 = 0x1fff3 =131059

asBits_= 0x1fff3 << 47 =0xFFF9800000000000= 18,444,914,486,360,932,352 =

1 11111111111 10011 00000000000000000000000000000000000000000000000

So the undefined Id is 10011.

Now let's do the same for null :

JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL

JSVAL_TAG_MAX_DOUBLE = 0x1FFF0

JSVAL_TYPE_NULL = 0x04

JSVAL_TAG_NULL = 0x1FFF0 | 0x04 = 0x1fff4 =131060

asBits_= 0x1fff4 << 47 = 0xFFFA000000000000 = 18,445,055,223,849,287,680 =

1 11111111111 10100 00000000000000000000000000000000000000000000000

So the null Id is 10100.

So eventually null and undefined are just constants predefined and distinguished by the engine , SpiderMonkey in our case .V8 also performs something similar to this ,you can explore its source code at V8 source.

A geeky answer to null vs undefined would be : it depends on the engine , for SpiderMonkey the difference is that undefined is 18,444,914,486,360,932,352 and null is 18,445,055,223,849,287,680 lol !!!!

Karim EL MRISSANI

Frontend Development Engineer | Next.js & React.js & React Native Specialist

1mo

This is a brilliant deep dive, MOHAMMED MHADA ! 🔥 Many stop at the usual “explicit vs. implicit” explanation when talking about null and undefined, but you went far beyond that, right down to the engine internals and memory-level representation. The way you dissected SpiderMonkey’s implementation, explained value tagging, and clarified how undefined and null are just constants with distinct bit patterns is top-tier content. This kind of curiosity-driven exploration is what truly sharpens a developer’s understanding. A must-read for anyone serious about mastering JavaScript! 👏🧠

To view or add a comment, sign in

Others also viewed

Explore topics