JavaScript Corners - Part 9
Global To-String
JavaScript Corners - Part 9
(This is Part 9 in my series on JavaScript corner cases).
Here’s another one.
In JavaScript, global variables are properties of the global object. By default, the global object is like any other, and inherits from the Object.prototype object. Object.prototype comes with a number of its own properties, such as the toString method. So, that means that toString is also a global variable1.
console.log('toString' in global); // prints true console.log(toString === global.toString); // prints true console.log(global.toString()); // prints [object global] console.log(toString()); // prints [object Undefined]. Why is this?
Everything seems expected, except the last line, which might seem a little confusing. The toString() call is clearly invoking a function using a reference to that function, where the base of the reference is the global object, right? (Take a look at my posts on references). So surely toString() and global.toString() mean the same thing?
Wrong.
There’s a subtlety here. The unqualified toString reference actually has a base value2 that is the global environment, which “knows about” the global object, but is not exactly the global object. The base object for the global environment is actually always the value undefined. See here in the spec. This is why it prints “[object Undefined]” .
To qualify as a global variable, there is actually an additional criterion. The property of the global object must not be listed in the set of unscopables on the global object. In this case,
toString
is not listed as an unscopable, since it was introduced into JavaScript before the existence of the unscopables feature, and for backwards compatibility it remains that way. ↩Recall that a reference has two components: the thing being referred on, and the name of the thing being referred to. For example, referring to the property named
x
on the objectobj
, in the case ofobj.x
↩