Why an empty Array type-converts to zero? +[]
just when I thought I understood something about type conversion in JavaScript, I stumbled with this:
+[]; // 0
Number([]); // 0
My first thought was that I should get NaN, just like if I try to convert an empty object to number:
+{}; // NaN
Number({}); // NaN
I have been searching about this for a while without any success...
Can somebody explain me why it gets converted to 0 and not to NaN?
Is this behavior standard?
Thanks.
Solution 1:
In a brief, there are two key points:
- The
toString
method of an empty array returns an empty string. - An empty string coerces to zero using the unary plus operator or the
Number
constructor called as a function (e.g.+"" === 0;
).
For example, we can use an object that defines a toString
method, and returns an empty string to have an equivalent result:
var obj = { toString: function () { return "";} };
+obj; // 0
Number(obj); // 0
This behavior is completely standard.
Now the long answer:
Both, the unary plus operator and the Number
constructor called as a function internally use the ToNumber
abstract operation.
ToNumber
will use two more internal operations, ToPrimitive
and [[DefaultValue]]
.
When the ToNumber
operation is applied to an Object, such the empty array in your example, it calls the ToPrimitive
operation, to get a representative primitive value and call ToNumber
again using that value [1].
The ToPrimitive
operation receive two arguments, a Value (which is your array object), and a hint type, which in this case is "Number" since we want to make numeric conversion.
ToPrimitive
calls the [[DefaultValue]]
internal method, also with a "Number" hint type.
Now, since the hint type we are using "Number", the [[DefaultValue]]
internal method now will try to invoke first the valueOf
method on the object.
Array objects don't have a specific valueOf
method, the method is the one inherited from Object.prototype.valueOf
, and this method simply returns a reference to the object itself.
Since the valueOf
method didn't result in a primitive value, now the toString
method is invoked, and it produces an empty string (which is a primitive value), then the ToNumber
operation will try to do String-Number conversion and it finally end up with 0
[1].
But now you might wonder, why an empty string coerces to zero?
+""; // 0
There is a complete grammar that is used when the ToNumber
internal operation is applied to a String type, the StringNumericLiteral
production.
It has some differences between a NumericLiteral, and one of those differences is that:
A StringNumericLiteral that is empty or contains only white space is converted to +0.