繁体   English   中英

为什么字符串到数字的比较在 Javascript 中起作用

[英]Why does string to number comparison work in Javascript

我正在尝试将来自 HTML 文本字段的值与整数进行比较。 它按预期工作。 条件是——

x >= 1 && x <= 999;

其中x是文本字段的值。 只要值介于 1-999(含)之间,条件返回true ,否则返回false 问题是,来自文本字段的值是字符串类型,我将它与整数类型进行比较。 可以进行这样的比较还是应该使用 parseInt() 将x转换为 integer ?

因为 JavaScript 定义>=<= (以及其他几个运算符)的方式允许它们将其操作数强制转换为不同的类型。 它只是运算符定义的一部分。

<><=>=的情况下,血淋淋的细节在规范的 §11.8.5 中列出 简短的版本是:如果两个操作数都是字符串(在从对象中强制转换之后,如有必要),它会进行字符串比较。 否则,它将操作数强制为数字并进行数字比较。

因此,您会得到有趣的结果,例如"90" > "100" (两者都是字符串,这是一个字符串比较)但"90" < 100 (其中一个是数字,这是一个数字比较)。 :-)

可以进行这样的比较还是应该使用 parseInt() 将 x 转换为 integer ?

这是一个见仁见智的问题。 有些人认为依靠隐含的强制是完全可以的; 其他人认为不是。 有一些客观的论据。 例如,假设您依赖隐式转换,这很好,因为您有那些数字常量,但后来您将x与从输入字段获得的另一个值进行比较。 现在您正在比较字符串,但代码看起来相同。 但同样,这是一个见仁见智的问题,你应该做出自己的选择。

如果您确实决定首先显式转换为数字,则parseInt可能是也可能不是您想要的,并且它不会做与隐式转换相同的事情。 以下是选项的概要:

  • parseInt(str[, radix]) - 尽可能多地将字符串的开头转换为一个整数(整数),忽略末尾的额外字符 所以parseInt("10x")10 x被忽略。 支持可选的基数(数字基数)参数,因此parseInt("15", 16)21 (十六进制的15 )。 如果没有基数,则假定为十进制,除非字符串以0x (或0X )开头,在这种情况下,它会跳过这些并假定为十六进制。 寻找新的0b (二进制)或0o (新式八进制)前缀; 这两个都解析为0 (某些浏览器过去将字符串以0开头视为八进制;该行为从未指定,并且在 ES5 规范中[特别禁止][2]。)如果找不到可解析的数字,则返回NaN

  • Number.parseInt(str[, radix]) - 与上面的parseInt完全相同的功能。 (从字面上看, Number.parseInt === parseInttrue 。)

  • parseFloat(str) - 与parseInt类似,但处理浮点数且仅支持十进制。 字符串上的额外字符再次被忽略,因此parseFloat("10.5x")10.5 (忽略x )。 由于仅支持十进制,因此parseFloat("0x15")0 (因为解析在x处结束)。 如果没有找到可解析的数字,则返回NaN

  • Number.parseFloat(str) - 与上面的parseFloat完全相同的函数。

  • 一元+ ,例如+str - (例如,隐式转换)使用浮点和 JavaScript 的标准数字表示法将整个字符串转换为数字(只有数字和小数点 = 十进制; 0x前缀 = 十六进制; 0b = 二进制 [ES2015+]; 0o前缀 = 八进制 [ES2015+];一些实现将其扩展为将前导0视为八进制,但不是在严格模式下)。 +"10x"NaN ,因为x未被忽略。 +"10"10+"10.5"10.5+"0x15"21+"0o10"8 [ES2015+], +"0b101"5 [ES2015+]。 有一个陷阱: +""0 ,而不是您可能期望的NaN

  • Number(str) - 完全像隐式转换(例如,像上面的一元+ ),但在某些实现上较慢。 (并不是说它可能很重要。)

  • 与零按位或,例如str|0 - 隐式转换,如+str ,但它还将数字转换为 32 位整数(如果字符串无法转换为有效数字,则将NaN转换为0 )。

因此,如果可以忽略字符串上的额外位,则parseIntparseFloat都可以。 parseInt对于指定基数非常方便。 一元+对于确保考虑整个字符串很有用。 任你选择。 :-)

对于它的价值,我倾向于使用这个功能:

const parseNumber = (str) => str ? +str : NaN;

(或修剪空白的变体。)注意它如何处理+""0的问题。

最后:如果您要转换为数字并想知道结果是否为NaN ,您可能会想这样做if (convertedValue === NaN) 但这行不通,因为正如 Rick 在下面指出的那样,涉及NaN的比较总是错误的。 相反,它是if (isNaN(convertedValue))

MDN's docs on Comparision声明操作数在比较之前转换为通用类型(与您正在使用的运算符):

更常用的抽象比较(例如 ==)在进行比较之前将操作数转换为相同的类型。 对于关系抽象比较(例如,<=),操作数首先转换为基元,然后转换为相同类型,然后再进行比较。

如果您使用的是严格比较,则只需要应用parseInt() ,在比较之前不会执行自动转换。

如果 var 是字符串,则应使用parseInt 添加 = 来比较datatype值:

parseInt(x) >== 1 && parseInt(x) <== 999;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM