Why is typeof null "object"?
Asked Answered
H

10

378

I'm reading 'Professional Javascript for Web Developers' Chapter 4 and it tells me that the five types of primitives are: undefined, null, boolean, number and string.

If null is a primitive, why does typeof(null) return "object"?

Wouldn't that mean that null is passed by reference (I'm assuming here all objects are passed by reference), hence making it NOT a primitive?

Hoberthobey answered 15/9, 2013 at 2:2 Comment(8)
Answer: Because the spec says so. This is generally regarded as a mistake.Slipcover
Note, typeof is an operator, not a function (and in fact you can omit the parentheses around what comes after it), so it does not makes sense to talk about passing by reference here. The book "JavaScript: The Good Parts" actually mentions the fact that typeof null === 'object' in section A.6 of appendix A entitled 'Awful Parts'.Naphthol
So what should we be using instead of typeof to check for the type of value a variable is holding? I'd love to know what it is between (boolean, string, number, array, object, function, symbol, null, undefined, NaN)Obsolescent
jQuery's $.type(null) would return "null", for some reason ....Insulator
Side note: typeof is an operator and not a function, so the parentheses in your code are not necessary - you could simply use the syntax typeof null.Footloose
I recommend doing a find and replace on your code base going from (typeof +(\w+) +={2,3} +"object") to -> ($2 && $1) in order to fix this issue anywhere it may exist. This will turn typeof arg === "object" into (arg && typeof arg === "object")Hypogeous
I puzzled for a bit about why the devs can't simply deprecate this unexpected behavior, especially when it dates back so far. Then I simply updated my gatekeeper code to if (typeof x !== 'object' || x === null) and moved on...Spittoon
See also: https://mcmap.net/q/21015/-why-is-null-an-object-and-what-39-s-the-difference-between-null-and-undefined/38522Salzhauer
P
306

From the MDN page about the behaviour of the typeof operator:

null

// This stands since the beginning of JavaScript
typeof null === 'object';

In the first implementation of JavaScript, JavaScript values were represented as a type tag and a value. The type tag for objects was 0. null was represented as the NULL pointer (0x00 in most platforms). Consequently, null had 0 as type tag, hence the "object" typeof return value. (reference)

A fix was proposed for ECMAScript (via an opt-in), but was rejected. It would have resulted in typeof null === 'null'.

Poundage answered 15/9, 2013 at 2:10 Comment(5)
It's a shame this change didn't at least make it into strict mode…Northway
People have been taking advantage of the quirk, and many code out there will have to be changed if this was not rejected, I guessBores
doesn't make sense why people would use this as a null check anyway. It doesn't make intuitive sense so why would they use it? Now the change can't be added because of bad coding.Dichlorodiphenyltrichloroethane
backwards incompatible like making typeof null === 'null' always causes problems that are more far-reaching and extensive than anybody can predict. I hate typeof null === 'object' too, but to argue it shouldn't be this way purely based off of ideals is to argue from ignorance.Riverhead
@JohnMiller now yes.. But this was in 2016, it had also a massive impact of course. But the longer we wait the harder it become to change it. At this point, it becomes harder and harder to make this change.Dorking
M
85

If null is a primitive, why does typeof(null) return "object"?

Because the spec says so.

11.4.3 The typeof Operator

The production UnaryExpression : typeof UnaryExpression is evaluated as follows:

  1. Let val be the result of evaluating UnaryExpression.
  2. If Type(val) is Reference, then
       a. If IsUnresolvableReference(val) is true, return "undefined".
       b. Let val be GetValue(val).
  3. Return a String determined by Type(val) according to Table 20.

enter image description here

Maskanonge answered 15/9, 2013 at 2:7 Comment(2)
To my knowledge, you can call methods on anything other than null and undefined.Maskanonge
@peter you cannot call methods on a string primitive, but thankfully string primitives (and number primitives and boolean primitives) are implicitly and automatically "auto-boxed" in String, Number, and Boolean wrappers when you use one of the primitives with a property reference operator (. or [ ]).Ontology
R
36

As has been pointed out, the spec says so. But since the implementation of JavaScript predates the writing of the ECMAScript spec, and the specification was careful not to correct foibles of the initial implementation, there's still a legitimate question about why it was done this way in the first place. Douglas Crockford calls it a mistake. Kiro Risk thinks it kinda sorta makes sense:

The reasoning behind this is that null, in contrast with undefined, was (and still is) often used where objects appear. In other words, null is often used to signify an empty reference to an object. When Brendan Eich created JavaScript, he followed the same paradigm, and it made sense (arguably) to return "object". In fact, the ECMAScript specification defines null as the primitive value that represents the intentional absence of any object value (ECMA-262, 11.4.11).

Rugg answered 15/9, 2013 at 2:16 Comment(1)
Since I can't find now the video I'll post this just for curious people and without any reference: Crockford explained how a zero value on resolving type of null pointed to the zero indexed element on the types array, so this was a clear developing bug which the Microsoft guys accidentally propagated when decompiling and recompiling JS for their browserSqueteague
D
10

From the book YDKJS

This is a long-standing bug in JS, but one that is likely never going to be fixed. Too much code on the Web relies on the bug and thus fixing it would cause a lot more bugs!

Devolution answered 26/10, 2016 at 6:19 Comment(3)
don't trust everything is written in a book. I really love that book, however, I cannot consider that a bug because the ECMA specification for JavaScript state that the type of null must be an object.Diglot
@Diglot This blog post explains why it's a bug. The fact that the spec states that typeof null is object simply means that the spec chose to incorporate the bug as part of the spec. Anyway, that's why I do consider it a bug. :)Fascism
And Brendan Eich explains why it was intentional. typeof null === "object" is not a bug, but a second-order effect of having to accommodate Java interoperability.Salzhauer
B
10

null

// This stands since the beginning of JavaScript
typeof null === 'object';

Short Answer:

This is a bug since the first release of ECMAScript which unfortunately can’t be fixed because it would break the existing code.

Explanation:

However, there is actually one logical explanation behind why null is an object in javascript.

In the initial version of JavaScript, values were stored in 32 bit units which consisted of a small type tag (1–3 bits) and the actual data of the value. The type tags were stored in the lower bits of the units. There were five of them:

000: object. The data is a reference to an object.
1: int. The data is a 31 bit signed integer.
010: double. The data is a reference to a double floating point number.
100: string. The data is a reference to a string.
110: boolean. The data is a boolean.

For all objects it was 000 as the type tag bits. null was considered to be a special value in JavaScript from its very first version. null was a representation of the null pointer. However, there were no pointers in JavaScript like C. So null simply meant nothing or void and was represented by all 0’s. Hence all its 32 bits were 0’s. So whenever the JavaScrit interpreter reads null, it considers the first 3 bits as type “object”. That is why typeof null returns “object”.

enter image description here

Resource: https://2ality.com/2013/10/typeof-null.html#:~:text=In%20JavaScript%2C%20typeof%20null%20is,it%20would%20break%20existing%20code.

Note:

A fix was proposed for ECMAScript (via an opt-in), but was rejected. It would have resulted in

typeof null === 'null'.

Balcer answered 11/2, 2023 at 16:0 Comment(0)
P
6

If null is a primitive, why does typeof(null) return "object"?

in short: it is bug in ECMAScript, and the type should be null

reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null

Part answered 6/5, 2015 at 10:37 Comment(2)
Nowhere in your reference does it state that it is a bug.Madness
And nowhere in the spec does it say typeof should return anything but "undefined", "object", "boolean", "number", "string", "function", and "symbol" (ECMAScript 2015)Fox
G
1

The ECMAScript specification identifies these language data types:

6.1.1 The Undefined Type
6.1.2 The Null Type
6.1.3 The Boolean Type
6.1.4 The String Type
6.1.5 The Symbol Type
6.1.6 Numeric Types
    6.1.6.1 The Number Type
    6.1.6.2 The BigInt Type
6.1.7 The Object Type

For historical reasons the typeof operator is not consistent with this categorisation in two cases:

  • typeof null == "object": this is unfortunate, but something we have to live with.
  • typeof of a function object evaluates to "function", even though according to the specification it has as data type Object.

Another operator -- instanceof -- can be used to know whether an object inherits from a certain prototype. For instance, [1,2] instanceof Array will evaluate to true.

One way to determine whether a value is an object, is to use the Object function:

if (Object(value) === value) // then it is an object; i.e., a non-primitive
Goldstone answered 2/9, 2021 at 10:51 Comment(0)
P
1

++The author's answer is:

I think it is too late to fix typeof. The change proposed for typeof null will break existing code

It's too late. Ever since Microsoft created its own JavaScript engine and copied all the features and bugs of the first engine version, all subsequent engines copied this bug and now it's too late to fix it.

JS_TypeOfValue(JSContext *cx, jsval v)
{
    JSType type = JSTYPE_VOID;
    JSObject *obj;
    JSObjectOps *ops;
    JSClass *clasp;

    CHECK_REQUEST(cx);
    if (JSVAL_IS_VOID(v)) {
        type = JSTYPE_VOID;
    } else if (JSVAL_IS_OBJECT(v)) {
        obj = JSVAL_TO_OBJECT(v);
        if (obj &&
            (ops = obj->map->ops,
                ops == &js_ObjectOps
                ? (clasp = OBJ_GET_CLASS(cx, obj),
                clasp->call || clasp == &js_FunctionClass)
                : ops->call != 0)) {
            type = JSTYPE_FUNCTION;
        } else {
            type = JSTYPE_OBJECT;
        }
    } else if (JSVAL_IS_NUMBER(v)) {
        type = JSTYPE_NUMBER;
    } else if (JSVAL_IS_STRING(v)) {
        type = JSTYPE_STRING;
    } else if (JSVAL_IS_BOOLEAN(v)) {
        type = JSTYPE_BOOLEAN;
    }
    return type;
}
Proust answered 7/6, 2022 at 7:47 Comment(1)
Where’s that code from?Scathe
P
0

In JavaScript null is "nothing". It is supposed to be something that doesn't exist. Unfortunately, in JavaScript, the data type of null is an object. You can consider it a bug in JavaScript that typeof null is an object. It should be null.

Paperhanger answered 20/12, 2019 at 11:46 Comment(0)
C
0

This is a bug remnant from javascript's first version.

"This is a bug and one that unfortunately can’t be fixed, because it would break existing code."

Reference and for more info: https://2ality.com/2013/10/typeof-null.html

Conformation answered 14/7, 2022 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.