Reputation: 18908
I don't understand why an empty array, or an array with only 1 "numerical" value can be used in certain calculations.
[] * [] === 0 //true
[2] * [2] === 4 //true
["2"] * ["2"] === 4 //true
However, it does not seem that is always the case with every operator.
[2] + [1] === 3 // false, actual result is "21"
[2] - [1] === 1 // true
I also checked these, and saw expected results:
[4] === "4" // false
[4] === 4 // false
In most cases, I would expect NaN
in any of these mathematical operations. What is it about JavaScript arrays that allows this? Is it because the array toString
method is being used somehow internally?
Upvotes: 1
Views: 66
Reputation: 8926
When you do mathematical operations on the arrays JavaScript converts them to the strings. But string doesn't have multiply operator and then JavaScript converts them to the numbers because you try to multiply them:
[] * [] === 0 // [] -> '' -> 0, result is 0 * 0
[2] * [2] === 4 // [2] -> '2' -> 2, result is 4 * 4
["2"] * ["2"] === 4 // ["2"] -> '2' -> 2, result is 4 * 4
String has a +
operator:
[2] + [1] === 3 // '2' + '1', result is "21"
but doesn't have a -
operator, therefore JavaScript converts them to the numbers too:
[2] - [1] === 1 // true, because they are numbers
===
it's strict equality, means that the objects being compared must have the same type.
[4] === "4" // false, you are comparing array with a string
[4] === 4 // false, you are comparing array with a number
Upvotes: 1
Reputation: 3217
In regards to +
, +
is a coercive operator on Strings
, irrespective of it being the lvalue
and rvalue
, I'll quote the specification here:
If
Type(lprim
) is String orType(rprim
) isString
, then Return theString
that is the result of concatenatingToString(lprim
) followed byToString(rprim
)
Multiplication however doesn't follow the same rules, it does however apply ToNumber
, which as you've noticed, casts a [Number]
to -> Number
(+
does this as well, but it is a later step in the operator's definition)
Your last statement is answered by two rules of the SameValue
algorithm defined in the spec, namely, if two values are of a different type, return false
, alternatively, if two objects refer to the ptr, return true. Thus
a = [1];
b = [1];
a === b; // false
Upvotes: 1
Reputation: 7900
The same ol'problem of having +
as string concatenation operator.
An array in Javascript is an Object. When you try to coerce objects into primitive values, there is an order to follow:
<obj>.toString()
<obj>.toNumber()
<obj>.toBoolean()
If you're using the *
operator, coerce into string is not possible, so the interpreter goes to toNumber()
.
When you're using the +
operator, the first attempt will be toString()
. Since +
is also the string concat operator, then the expression will be evaluated as an array.
Yeah, javascript can get ugly.
Some further details can be found here.
Upvotes: 1
Reputation: 10695
The arrays are coerced into strings, such that [] == ""
, [1] == "1"
, and [1, 2] == "1,2"
.
When you do certain mathematical operations on strings, they are coerced into Number
types.
For example, when you do [2] * [2]
it becomes "2" * "2"
which becomes 2 * 2
. You can even mix types and do [2] * 2
or "2" * [2]
.
When you try to use +
, it attempts to concatenate the strings instead of coercing the strings to numbers. That's why "2" + "2"
, "2" + [2]
, and [2] + [2]
each give you "22"
.
Upvotes: 5