我不明白为什么一个空数组,或一个只有1"数字"值可用于某些计算。
[] * [] === 0 //true
[2] * [2] === 4 //true
["2"] * ["2"] === 4 //true
但是,似乎每个运营商都不会这样。
[2] + [1] === 3 // false, actual result is "21"
[2] - [1] === 1 // true
我也检查了这些,并看到了预期的结果:
[4] === "4" // false
[4] === 4 // false
在大多数情况下,我希望在任何这些数学运算中NaN
。什么是JavaScript数组允许这个?是因为数组toString
方法在某种程度上被内部使用了吗?
答案 0 :(得分:5)
数组被强制转换为字符串,例如[] == ""
,[1] == "1"
和[1, 2] == "1,2"
。
当您对字符串执行某些数学运算时,它们会被强制转换为Number
类型。
例如,当您执行[2] * [2]
时,"2" * "2"
变为2 * 2
。您甚至可以混合使用类型并执行[2] * 2
或"2" * [2]
。
当您尝试使用+
时,它会尝试连接字符串,而不是将字符串强制转换为数字。这就是为什么"2" + "2"
,"2" + [2]
和[2] + [2]
分别为您提供"22"
的原因。
答案 1 :(得分:1)
将+
作为字符串连接运算符的相同问题。
Javascript中的数组是一个Object。当您尝试将对象强制转换为原始值时,需要遵循以下命令:
<obj>.toString()
<obj>.toNumber()
<obj>.toBoolean()
如果您正在使用*
运算符,则无法强制转换为字符串,因此解释程序将转到toNumber()
。
当您使用+
运算符时,首次尝试将为toString()
。由于+
也是字符串concat运算符,因此表达式将被计算为数组。
是的,javascript可能会变丑。
可以找到更多详细信息here。
答案 2 :(得分:1)
关于+
,+
is a coercive operator on Strings
,无论是lvalue
还是rvalue
,我都会引用此处的说明:
如果
Type(lprim
)是字符串或Type(rprim
)是String
,则返回String
这是连接ToString(lprim
)后跟的结果ToString(rprim
)
Multiplication however doesn't follow the same rules,然而它会应用ToNumber
,正如您所注意到的那样,将[Number]
投射到 - &gt; Number
(+
也会这样做,但这是运营商定义中的后续步骤)
您的上一个语句由规范中定义的SameValue
算法的两个规则回答,即,如果两个值的类型不同,则返回false
,或者,如果两个对象引用ptr,返回true。因此
a = [1];
b = [1];
a === b; // false
答案 3 :(得分:1)
当您对数组执行数学运算时,JavaScript会将它们转换为字符串。但字符串没有乘法运算符,然后JavaScript会将它们转换为数字,因为您尝试将它们相乘:
[] * [] === 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
字符串有一个+
运算符:
[2] + [1] === 3 // '2' + '1', result is "21"
但没有-
运算符,因此JavaScript也将它们转换为数字:
[2] - [1] === 1 // true, because they are numbers
===
它的严格相等,意味着被比较的对象必须具有相同的类型。
[4] === "4" // false, you are comparing array with a string
[4] === 4 // false, you are comparing array with a number