要了解测试用例的结果,您需要了解使用任何关系运算符比较数组或任何其他对象时会发生什么。
长话短说,对象在使用任何关系运算符进行比较之前先转换为字符串.
(如果您不想阅读有关对象到基元转换的内容,请跳到答案的末尾.)
ToPrimitive抽象操作
为了将对象转换为原始值,JavaScript 执行到原语带有两个参数的抽象操作:
-
input
:应转换为原始值的对象
-
preferredType
:可选的第二个参数,指定将对象转换为原始值时应优先使用的类型
对于对象到原始类型的转换,到原语抽象操作调用另一个抽象操作,称为普通到原始
OrdinaryToPrimitive 抽象操作
对于对象到原始类型的转换,到原语抽象操作调用OrdinaryToPrimitive有两个参数的抽象操作:
-
O
:应转换为原始值的对象
-
hint
:将对象转换为原始值时应优先选择的类型
到原语抽象操作设置hint
如下:
- If the
preferredType
is a string
, set hint
to string
- If the
preferredType
is a number
, set hint
to number
- If
preferredType
未指定,设置hint
to number
普通到原始抽象操作使用以下三种算法将对象转换为原始值:
-
首选字符串: If hint
is string
,返回一个原始值,如果可以转换为字符串,则首选字符串值
-
首选号码: If hint
is number
,返回一个原始值,如果可以转换为数字,则首选数字值
-
没有偏好:该算法不表达应返回什么类型的原始值的偏好,并让对象定义应返回什么类型的原始值。如果hint
is default
或者没有hint
,该算法用于将对象转换为原始值。
它允许对象覆盖默认值ToPrimitive
行为。内置对象中,只有Date
and Symbol
对象覆盖默认值ToPrimitive
行为。Date
and Symbol
对象将该算法实现为prefer-string
而所有其他内置对象都将该算法实现为prefer-number
(对象可以覆盖默认值ToPrimitive
通过实施行为符号到原语 method.)
所有对象都继承两个用于将对象转换为原始值的方法。这两种方法是:
对象到原始数据的转换涉及到调用上面提到的方法和上面提到的对象到原始数据转换算法,这两个方法的调用顺序不同。
首选字符串
该算法首先调用.toString()
方法,如果结果值是原始值,则 javascript 使用返回的原始值,即使它不是字符串。
If the .toString()
方法不存在或返回一个object
, then .valueOf()
方法被调用。如果.valueOf()
方法返回一个原始值,然后使用该值TypeError
被抛出。
首选号码
该算法与prefer-string
是它首先调用.valueOf()
方法然后.toString()
method.
没有偏好
当没有首选类型 or hint或者如果首选类型 is default
, 默认情况下,prefer-number
使用算法。
对象可以覆盖此行为以及所有内置对象,只有Date
and Symbol
覆盖此默认值ToPrimitive
转换行为。Date
and Symbol
use prefer-string
没有时的算法首选类型 or a hint or the 首选类型是默认的。
现在回到你的问题,关系运算符,即<, >=, <, <=
可用于比较字符串和数字。如果这些运算符的任一操作数是object
,使用以下方法将其转换为原始值prefer-number
算法。因此,当您使用关系运算符比较两个数组时,JavaScript 会尝试使用以下方法将每个数组转换为原始值:prefer-number
算法。
正如刚才提到的,prefer-number
算法首先调用.valueOf()
方法。如果返回值是原始值,则使用该值,否则.toString()
方法被调用。
默认实现.valueOf()
方法只是返回对象本身而不是返回原始值,因此 javascript 总是最终调用.toString()
方法当使用prefer-number
算法。
When .toValue()
在数组上调用方法,它只是返回调用该方法的数组。然后 JavaScript 调用.toString()
方法对此返回的数组。什么时候.toString()
方法在数组上调用,它将数组的所有元素转换为字符串,然后将所有字符串连接在一起,每个字符串之间用逗号连接。
所以当你比较时[1] > [2]
,你正在比较'1' > '2'
和类似地[1,2] > [1,1]
被转换为'1,2' > '1,1'
.
当字符串通过其 unicode 代码点进行比较时,'1' > '2'
评估为false
and '1,2' > '1,1'
评估为true
.