在 JavaScript 中比较字符串时,为什么一个字符串比另一个大?

IT技术 javascript string compare
2021-01-30 23:40:03

我从一本书中看到这段代码:

var a = "one";
var b = "four";
a>b; // will return true

但它没有提到为什么“一”比“四”大。我试过了c = "a",它比a和b小。我想知道 JavaScript 如何比较这些字符串。

5个回答

因为,在许多编程语言中,字符串是按字典顺序比较的

您可以将其视为字母排序的更高级版本,不同之处在于字母排序仅涵盖 26 个字符az.


这个答案是对一个问题,但逻辑是完全一样的。另一个好方法:String Compare "Logic"

解释字符“值”的最佳解释是将用户指向一个 ASCII 表,该表表示每个字符的十进制值。
2021-03-13 23:40:03
如有疑问,请找出规范。在这种情况下,请参阅ECMAScript Spec 的第 11.8.5 节. 当然,为了更容易解析答案,SO 档案也有效。:-)
2021-03-24 23:40:03
@ps2goat 好点。随意建议对此答案进行编辑以添加:)
2021-03-25 23:40:03

“one”以“o”开头,“four”以“f”开头,“o”在字母表中比“f”晚,因此“one”大于“four”。有关JavaScript 字符串比较的一些不错的示例,请参阅此页面(附有解释!)。

Javascript 对>运算符使用字典顺序'f' 继续 'o' 所以比较"one" > "four"返回true

ECMAScript语言规范的第11版“抽象关系比较”条款定义了如何计算x < y当表达式被还原(即x > y)时,我们应该计算结果y < x

所以要解决"one" > "four"我们必须解决"four" < "one"

同一个条款是这样说的:

字符串的比较对代码单元值序列使用简单的字典顺序。

这如果两个操作数都是字符串:

  1. 如果 Type(px) 是 String 并且 Type(py) 是 String,那么
    • 如果IsStringPrefix (py, px) 为真,则返回假。
    • 如果IsStringPrefix (px, py) 为真,则返回真。
    • 令 k 为最小的非负整数,使得 px 内索引 k 处的代码单元与 py 内索引 k 处的代码单元不同。(必须有这样的 ak,因为 String 都不是另一个的前缀。)
    • 让 m 是整数,它是 px 内索引 k 处代码单元的数值。
    • 设 n 是整数,它是 py 中索引 k 处代码单元的数值。
    • 如果 m < n,则返回 true。否则,返回false。

(我们可以放心地忽略此示例的前两点)

那么让我们看看“四”的代码单元:

[..."four"].map(c => c.charCodeAt(0));
//=> [102, 111, 117, 114]

而对于“一”:

[..."one"].map(c => c.charCodeAt(0));
//=> [111, 110, 101]

所以现在我们必须找到k的值(从 0 开始),其中m[k]n[k]都不同:

|   | 0   | 1   | 2   | 3   |
|---|-----|-----|-----|-----|
| m | 102 | 111 | 117 | 114 |
| n | 111 | 110 | 101 |     |

我们可以看到在 0 处m[0]n[0]是不同的。

由于m[0] < n[0]为真,"four" < "one"则为真,因此"one" > "four"为真。


什么"☂︎" < "☀︎"回报?

[..."☂︎"].map(c => c.charCodeAt(0))
//=> [9730, 65038]
[..."☀︎"].map(c => c.charCodeAt(0))
//=> [9728, 65038]
|   | 0    | 1     |
|---|------|-------|
| m | 9730 | 65038 |
| n | 9728 | 65038 |

既然9730 < 9728是假的,那"☂︎" < "☀︎"就是假的,这很好,因为雨并不比太阳好(显然;)。

当您<=在 JavaScript 中使用像字符串这样的关系运算符时,您是在比较它们的底层 Unicode 代码单元¹,从头开始一次一个,第一次发现任何差异时停止。"one" > "four"为真,因为"o"(代码单元 111)大于至"f"(代码单元 102)。由于在第一个字符中发现差异,其余字符将被忽略。如果有"fb" > "fa""f"则将比较两个s,发现相同,然后比较每个字符串("b""a"的下一个字母如果字符串的长度不同并且较长的字符串从较短的字符串开始,则较短的字符串“小于”较长的字符串 ( "aaa" < "aaab"is true)。

这曾经被规范中抽象关系比较操作所涵盖,但现在是IsLessThan操作。


¹ 关系运算符使用代码单元这一事实是将它们与字符串一起使用的一个很好的理由,因为在许多情况下,代码单元顺序不能很好地映射到人们基于他们的语言的期望("é"< "z"is false,这可能没什么意义对讲法语的人);相反,使用localeCompare, 可能带有一些可选设置,以便与字符串包含的语言进行适当的比较("é".localeCompare("z", "fr") < 0is true,因为语言环境中以正确的词典顺序é出现在前面)。z"fr"