为什么字符串与数字的比较在Javascript中有效

Why does string to number comparison work in Javascript

本文关键字:Javascript 有效 比较 字符串 数字 为什么      更新时间:2023-09-26

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

x >= 1 && x <= 999;

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

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

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

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

可以

像这样进行这种比较还是应该使用 parseInt() 将 x 转换为整数?

这是一个见仁见智的问题。有些人认为依靠隐性胁迫是完全可以的;其他人则认为不是。有一些客观的论点。例如,假设您依赖于隐式转换,这很好,因为您有这些数字常量,但后来您将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) - 与隐式转换完全相同(例如,如上面的一元+),但在某些实现上较慢。(并不是说这可能很重要。

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

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

对于它的价值,我倾向于使用这个函数:

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

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

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

MDN 关于比较的文档指出,在比较(与您正在使用的运算符)之前,操作数被转换为通用类型:

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

如果您

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

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

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