为什么将0与长度为1的数组进行比较会返回true,而与长度大于2的数组进行比较会返回false?例如:
var a=[] //undefined
0<a //returns false
a.push(1) // [1]
0<a // returns true
a.push(2) // [1, 2]
0<a // return false
a.push(3) // [1, 2, 3]
0<a // return false
为什么将0与长度为1的数组进行比较会返回true,而与长度大于2的数组进行比较会返回false?例如:
var a=[] //undefined
0<a //returns false
a.push(1) // [1]
0<a // returns true
a.push(2) // [1, 2]
0<a // return false
a.push(3) // [1, 2, 3]
0<a // return false
toString
方法,
Array
对象覆盖了Object
的toString
方法。对于数组对象,toString 方法将数组连接起来,并返回一个包含由逗号分隔的每个数组元素的字符串。当 JavaScript 要将数组表示为文本值或在字符串连接中引用数组时,自动调用
toString
方法。
就像使用 join
方法一样,然后将其转换为数字。
what you do what you get result array string number
------------ ------------ ------ --------- -------- ----------
var a = [];
0 < a 0 < 0 false [] -> '' -> 0
a.push(1);
0 < a 0 < 1 true [1] -> '1' -> 1
a.push(2);
0 < a 0 < NaN false [1, 2] -> '1,2' -> NaN
a.push(3);
0 < a 0 < NaN false [1, 2, 3] -> '1,2,3' -> NaN
- 令primValue为ToPrimitive(argument, hint Number)。
- 返回ToNumber(primValue)。
ToPrimitive
函数在7.1.1节中有描述。
@@toPrimitive
是一个符号,你可以通过Symbol.toPrimitive
访问它。问题在于Array
没有这个属性,所以进程继续到以下步骤:
- 返回OrdinaryToPrimitive(input,hint)。
当用参数O和hint调用抽象操作OrdinaryToPrimitive时,执行以下步骤:
- 如果hint为“string”,则
a. 让methodNames为«"toString", "valueOf"»。- 否则,
a. 让methodNames为«"valueOf", "toString"»。
由于hint是“number”,我们处于第二种情况。接下来的步骤解释了按顺序应用这些方法。
现在,Array.prototype.valueOf
只返回数组本身,因此由于类型是对象(即数组),所以以下子步骤将不会返回:
5.c.iii 如果 Type(result) 不是 Object,则返回 result。
因此,备用方法启动,并在数组上调用 toString
。
因此,将数组转换为字符串。这是上面列出的两个步骤中的第一个步骤的结果:
- 让 primValue 成为 ToPrimitive(argument, hint Number)。
- 返回 ToNumber(primValue)。
第二步更简单:然后将字符串转换为数字,这在 第7.1.3.1节 中有描述。
作为Array.prototype.toString方法创建逗号分隔列表,一旦数组有多个元素,这些字符串就会变成无效数字。如规范所述,返回值为NaN。任何与NaN的<比较都将返回false,这解释了您得到的输出结果。Number(a); //insert this after each line
push(2)
和 push(3)
返回 NaN
? - apiresconsole.log(a.toString(), Number(a.toString())
- epascarello[1,2]
变成了 "1,2"
。[1,2] == "1,2" // <- true
。Object.freeze
使数组不可变,你仍然会得到这种强制转换。 - trincotvar b[]
b.push(8);
b == 8 //true (but b === 8 is false!)
如果数组中有多个元素,则数组类型为array[number],这与number不同,因此您无法将其与数字进行比较。
这就是为什么在您的代码中执行以下操作后:
var a=[]
0<a
a.push(1)
0<a
你得到了true,因为a的值现在是“1”,大于0。但是,在下一次push之后,该值变成了[1,2],它不是一个数字(NaN),这就是为什么你得到了false。
就比较而言,JavaScript 通常会尝试将操作数转换为数字(优先考虑)。
看这个例子:
console.log("test" == true);//false
console.log("test" == false);//false
为什么?因为“test”试图被转换成数字,所以Number("test")会得到NaN,而NaN既不等于true也不等于false。
0<a becomes 0 < Number(a) becomes 0 < 0 returns "false".
Number
能够将其强制转换为数字,但是当你添加多个元素时,应该返回什么数字呢?
在这种情况下,Number(arr) 变成了 NaN,而且 0 不小于 NaN。a.length
。