为什么只有一个数字项的数组可以用一些算术运算

Why is an array with only 1 numerical item usable with some arithmetic?

本文关键字:算术运算 数组 有一个 数字 为什么      更新时间:2023-09-26

我不明白为什么在某些计算中可以使用空数组或只有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方法在内部使用了吗?

数组被强制为字符串,例如[] == ""[1] == "1"[1, 2] == "1,2"

当您对字符串执行某些数学运算时,它们会被强制转换为Number类型。

例如,当执行[2] * [2]时,它将变为"2" * "2",也就是2 * 2。您甚至可以混合类型并执行[2] * 2"2" * [2]

当您尝试使用+时,它会尝试连接字符串,而不是将字符串强制为数字。这就是为什么"2" + "2""2" + [2][2] + [2]分别给你"22"

+作为字符串串联运算符的问题相同。

Javascript中的数组是一个Object。当您试图将对象强制为基元值时,需要遵循以下顺序:

  1. <obj>.toString()
  2. <obj>.toNumber()
  3. <obj>.toBoolean()

如果您使用的是*运算符,那么强制转换为字符串是不可能的,所以解释器转到toNumber()

当您使用+运算符时,第一次尝试将是toString()。由于+也是字符串concat运算符,因此表达式将被计算为数组。

是的,javascript可能会变得丑陋。

编辑:

一些进一步的细节可以在这里找到。

关于++Strings上的强制算子,无论它是lvalue还是rvalue,我都会在这里引用规范:

如果Type(lprim)是String或Type(rprim)是String,则返回作为级联ToString(lprim的结果的String)之后ToString(rprim

然而,乘法并不遵循相同的规则,它确实应用了ToNumber,正如您所注意到的,它将[Number]强制转换为->Number+也这样做,但这是运算符定义中的后续步骤)

您的最后一条语句由规范中定义的SameValue算法的两条规则回答,即,如果两个值的类型不同,则返回false;或者,如果有两个对象引用ptr,则返回true。因此

a = [1];
b = [1];
a === b; // false

当您对数组进行数学运算时,JavaScript会将它们转换为字符串。但是string没有乘法运算符,然后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

String有一个+运算符:

[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