Why is typeof null an object in Javascript? published: 10th December 2024
All values in JS are either
primitives or
objects.
Primitives
- Undefined
- Null
- Boolean
- Number
- String
- BigInt
- Symbol
Primitives are immutable, you cannot add properties to them.
> var str = "xyz";
> str.foo = "abc"; // try to add property "foo"
> str.foo // no change undefined
Primitives are compared by value, they
are equal if they hold the same value
> "xyz" === "xyz";
true
Objects: all non-primitive values are objects and they are mutable.
> var obj = {};
> obj.foo = "abc"; // add property "foo"
abc
> obj.foo // "foo" has been added
abc
Objects are compared by reference. Two
objects are considered equal only if they are in fact the same
object.
> {} === {};
false
> var obj = {};
> obj === obj
true
To find the type of a variable JS provides the operator
typeof which returns a string indicating
the type of the operand's value.
> console.log(typeof 10); // output: "number"
> console.log(typeof 'abc'); // output: "string"
> console.log(typeof false); // output: "boolean"
> console.log(typeof undeclaredVariable); // output: "undefined"
Ok so let's look at what happens when we check the typeof null
> console.log(typeof null); // output: "object"
hhhmmm something doesn't look right, how can a primitive value have a type of non-primitive value? What kind of bug is this in JS? This quirky JS behaviour comes from its early implementation where the values were stored in 32 bit units and the type information was encoded using a bit level approach where the type value could be quickly computed by looking at the lower bits of a 32 bit memory unit. There were five of them:
- 000: data is reference to an object
- 001: data is 31 bit signed integer
- 010: data is reference to a floating point number
- 100: data is a reference to string
- 110: data is a boolean
If the lowest bit (the rightmost bit) is 1 the tag is 1 bit long. If the lowest bit is 0 the type tag is 3 bits long which provides two additional bits for four types. Two values were special and differed in implementation: undefined (JSVAL_VOID) the integer -230 which is -1073741824 (a number outside the integer range) and null (JSVAL_NULL) the machine code NULL pointer or an object type tag plus a reference that is zero. The system examined the type tag for null and rightfully said it's an "object". Remember JS was created as a prototype in 10 days by Brendan Eich so fore sighting such a bug was not really possible.