缘由
Chrome浏览器的版本号突破100,由此引发的版本号比较问题,有一种写法最终执行结果就是
"100" < "99"
但是结果并不符合预期返回 false ,相反结果是 true 。
问题
问题在于这很不符合直觉,更符合直觉的方式是各自都转成数字然后再比较。
验证
以下是 Chrome 验证过程
"100" < "99"
true
"100".charCodeAt(0)
49
"99".charCodeAt(0)
57
"100".charCodeAt(0) < "99".charCodeAt(0)
true
返回结果确确实实是 true ,"100" 小于 "99"。
原理
1. 参考小于号 Less than (<)中的描述
The operands are compared using the [Abstract Relational Comparison](https://tc39.es/ecma262/#sec-abstract-relational-comparison) algorithm, which is roughly summarized below:
- First, objects are converted to primitives using [`Symbol.ToPrimitive`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive) with the `hint` parameter be `'number'`.
- If both values are strings, they are compared as strings, based on the values of the Unicode code points they contain.
- Otherwise JavaScript attempts to convert non-numeric types to numeric values:
- Boolean values `true` and `false` are converted to 1 and 0 respectively.
- `null` is converted to 0.
- `undefined` is converted to `NaN`.
- Strings are converted based on the values they contain, and are converted as `NaN` if they do not contain numeric values.
- If either value is [`NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN), the operator returns `false`.
- Otherwise the values are compared as numeric values.
如果两个值都是字符串,则根据它们包含的 Unicode 代码点的值进行比较。
2. 参考Abstract Relational Comparison中的描述(仅截取字符串比较相关描述)
If Type(px) is String and Type(py) is String, then
- If IsStringPrefix(
py,px) is true, return false. - If IsStringPrefix(
px,py) is true, return true. - Let
kbe the smallest non-negative integer such that the code unit at indexkwithinpxis different from the code unit at indexkwithinpy. (There must be such ak, for neither String is a prefix of the other.) - Let
mbe the integer that is the numeric value of the code unit at indexkwithinpx. - Let
nbe the integer that is the numeric value of the code unit at indexkwithinpy. - If
m<n, return true. Otherwise, return false.
总结一下
- 前两条描述的是如果 x 是 y 前缀,则返回 true,否则是 false
- 后三条描述的是 x 、 y 不互为前缀,就逐个比较每个字符对应的 Unicode