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.
The length property sets or returns the number of elements in an array. By knowing the number of elements in the array, you can tell if it is empty or not. An empty array will have 0 elements inside of it.
Because they are not same object, different object never identical equal, so the result is false .
arrays are objects, objects are truthy. just ask for array. length, if not zero, it will be truthy. when you explicitly convert to Boolean, the array turns into an empty string first, then the empty string turns into false.
An array value can be non-empty, empty (cardinality zero), or null. The individual elements in the array can be null or not null. An empty array, an array value of null, and an array for which all elements are the null value are different from each other. An uninitialized array is a null array.
In a brief, there are two key points:
toString
method of an empty array returns an empty string.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With