roro
roro

Reputation: 213

Why does getPrototypeOf 'null' give an error?

So I know 'null' is a type of 'object'

However, when I do Object.getProtoTypeOf(null) I get an error. Same goes for instanceof, which is kinda the same thing.

If null is a type of Object...it should be in it's prototype chain, right?

// 'object'
typeof null;  

// gives error - Cannot convert undefined or null to object
Object.getPrototypeOf(null);

// false ---- why?
null instanceof Object

Is there something I'm missing, or JS is just too hippie ?!

Upvotes: 2

Views: 1282

Answers (1)

raina77ow
raina77ow

Reputation: 106385

See, null is not an object. It's true that typeof null evaluates to 'object', but it actually came from a limitation and may be considered a quirk - a bug to some extent - of JavaScript. Quoting this article:

The "typeof null" bug is a remnant from the first version of JavaScript. In this version, 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.

That is, the lowest bit was either one, then the type tag was only one bit long. Or it was zero, then the type tag was three bits in length, providing two additional bits, for four types. Two values were special:

  • undefined (JSVAL_VOID) was the integer −230 (a number outside the integer range).
  • null (JSVAL_NULL) was the machine code NULL pointer. Or: an object type tag plus a reference that is zero.

It should now be obvious why typeof thought that null was an object: it examined its type tag and the type tag said “object”.

Now, for the rest operations null is treated as a primitive value. That's why, for example, null instanceof Object returns false - any primitive will, as it cannot be an instance. Compare 42 instanceof Number (false) with typeof 42 === 'number'.


For Object.getPrototypeOf(null), it's a bit different. In ES5 standard this function should throw an exception if its argument is a primitive - any primitive:

When the getPrototypeOf function is called with argument O, the following steps are taken:

  • If Type(O) is not Object throw a TypeError exception.
  • Return the value of the [[Prototype]] internal property of O.

However, in ES2015 they changed it:

When the getPrototypeOf function is called with argument O, the following steps are taken:

  • Let obj be ToObject(O).
  • ReturnIfAbrupt(obj).
  • Return obj.[[GetPrototypeOf]]().

... so Object.getPrototypeOf(42) now works. Yet both Object.getPrototypeOf(undefined) and Object.getPrototypeOf(null) throw the same error:

Uncaught TypeError: Cannot convert undefined or null to object

This exception is thrown by ToObject() method (doc) - and it makes sense, as one cannot 'box' null and undefined. In some ways it's similar to the error you get when trying to access a property of null or undefined.

Upvotes: 4

Related Questions