Why using the unary operator + on an array gives inconsistent results in javascript?

arrays, javascript

Solution

The Unary + operator internally uses the ToNumber abstract operation.

The ToNumber abstract operation, when applied to objects, calls the object's `toString` method (by way of the `[[DefaultValue]]` internal method) and then re-applies the ToNumber operation on the resulting string representation.

The interesting thing here is Array's `toString` method. Note that `[false].toString()` is quite different from `[undefined].toString()` or `[null].toString()`. When we inspect the specification for `Array.prototype.toString`, we see that internally it uses `Array.prototype.join`. Step 8 of the `join` algorithm says:

- If element0 is `undefined` or `null`, let R be the empty String; otherwise, Let R be ToString(element0).

Thus, any array containing a single `null` or `undefined` stringifies to the empty string (which ToNumber number-ifies to `0`), while other values will stringify to some other string (which will then number-ify to `NaN` if the string is non-numeric).

`+[undefined]` is the same as `+""`, while `+[false]` is the same as `+"false"`.

Problem

I was doing some testing converting values to integer in javascript and printing the output in the console when I came across with this strange behavior. ``` console.log(+[]) ==> 0 console.log(+[123]) ==> 123 console.log(+['123']) ==> 123 console.log(+[123, 456]) ==> NaN console.log(+['123asdf']) ==> NaN ``` I thought the values were being converted using parseInt but turns out it wasn't so I went to the javascript conversion table http://www.w3schools.com/js/js_type_conversion.asp This give me a better idea on how conversions are performed. Acording to this table ``` [] => 0 [20] => 20 [10,20] => NaN ["twenty"] =>NaN ["ten","twenty"] => NaN ``` So aparently they take the first value of the array and convert it using the specified rules. The rules of parseInt does not apply. I tested to reach this conclusion. You can nested it all you want, it will give you the same result. ``` console.log(+[[[[[[[[[[[10]]]]]]]]]]]) => 10 ``` So then I thought, ok if that's the case ``` console.log(+[undefined]) will return NaN console.log(+[null]) will return 0 console.log(+[false]) will return 0 ``` those are the values expected from the javascript conversion table to integer but turns out ``` console.log(+[undefined]) => 0 console.log(+[null]) => 0 console.log(+[false]) => NaN ``` The last is the most strange because false is converted to 0, not to NaN. Can someone explain the strange behaviour or explain how this conversion is performed?

Original source