数组上“大于”(以及另一个不等式比较运算符)的行为

2023-12-11

我找不到任何描述或任何提及如何>, <, <= and >=在 JavaScript 中比较两个数组时运算符的行为。

我能想到的唯一一件微不足道的事情是,两个数组通过每个相对索引的两个元素进行比较,但在测试之后 - 我没有得到我预期的结果。

那么数组是如何比较的呢?

几个测试用例:

console.log([1] > [2]); // FALSE - ok
console.log([2] > [1]); // TRUE - ok
console.log([2] > [2]); // FALSE - ok
console.log([1,2] > [2,3]); // FALSE - In case two elements in each index are compared, and the answer is "If all >" - ok  
console.log([2,2] > [1,1]); // TRUE - In case two elements in each index are compared, and the answer is "If all >" - ok
console.log([1,2] > [1,1]); // TRUE - In case two elements in each index are compared, and the answer is "If all >" - Unexpected
// More cases with 3 elements:
console.log([1,2,1] > [1,2,2]); // FALSE
console.log([1,1,1] > [1,1,2]); // FALSE
console.log([1,3,1] > [1,3,0]); // TRUE
console.log([1,1,1] > [1,1,2]); // FALSE

要了解测试用例的结果,您需要了解使用任何关系运算符比较数组或任何其他对象时会发生什么。

长话短说,对象在使用任何关系运算符进行比较之前先转换为字符串.

(如果您不想阅读有关对象到基元转换的内容,请跳到答案的末尾.)

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.)

所有对象都继承两个用于将对象转换为原始值的方法。这两种方法是:

  • .valueOf()
  • .toString()

对象到原始数据的转换涉及到调用上面提到的方法和上面提到的对象到原始数据转换算法,这两个方法的调用顺序不同。

首选字符串

该算法首先调用.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.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数组上“大于”(以及另一个不等式比较运算符)的行为 的相关文章