为什么在Javascript中字符串和数字的比较是可行的

8
我将尝试将来自 HTML 文本字段的值与整数进行比较。它按预期工作。条件是 -
x >= 1 && x <= 999;

x是文本字段的值时,条件返回true,只要该值在1-999(包括1和999)之间,否则返回false。 问题在于,从文本字段中获取的值是字符串类型,而我正在将其与整数类型进行比较。这种比较方式是否正确?或者我应该使用parseInt()将x转换为整数类型?


你不需要使用parseInt()。在比较数字和字符串时,JavaScript会尽可能地将字符串转换为数字。 - Rick Hitchcock
3个回答

18
因为JavaScript定义了>=<=(以及其他几个运算符)的方式,使它们可以强制将其操作数转换为不同类型。这只是运算符定义的一部分。
对于<><=>=,详细信息在规范的§11.8.5节中有说明。简短的版本是:如果两个操作数都是字符串(在必要时从对象中强制转换),则进行字符串比较。否则,它将操作数强制转换为数字并进行数字比较。
因此,您会得到有趣的结果,例如"90" > "100"(它们都是字符串,这是一个字符串比较),但"90" < 100(其中一个是数字,这是一个数字比较)。 :-)

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

这是一个观点问题。有些人认为依赖隐式强制转换完全没问题,而另一些人则不这么认为。有一些客观的论据。例如,假设你依赖隐式转换,并且因为你有那些数字常量而没有问题,但后来你将x与从输入字段得到的另一个值进行比较。现在你正在比较字符串,但代码看起来是相同的。但再次强调,这是一个观点问题,你应该自己做出选择。
如果你决定先明确地转换为数字,parseInt可能并不是你想要的,它也不能像隐式转换那样工作。以下是一些选项:
  • parseInt(str[, radix]) - 将字符串开头尽可能多的部分转换为整数,忽略结尾的额外字符。因此,parseInt("10x")10x 被忽略了。支持可选参数 radix(数字基数),所以 parseInt("15", 16)21(十六进制中的 15)。如果没有 radix,则默认为十进制,除非字符串以 0x(或 0X)开头,这时会跳过它们并假定为十六进制。不会查找新的 0b(二进制)或 0o(新式八进制)前缀;两者都解析为 0(一些浏览器曾将以 0 开头的字符串视为八进制;这种行为从未被规定,并且在 ES5 规范中[明确禁止][2]。)如果找不到可解析的数字,则返回 NaN

  • Number.parseInt(str[, radix]) - 与上面的 parseInt 函数完全相同。(实际上,Number.parseInt === parseInttrue。)

  • parseFloat(str) - 与 parseInt 类似,但处理浮点数并且只支持十进制。同样,字符串中的额外字符被忽略,因此 parseFloat("10.5x")10.5x 被忽略)。由于仅支持十进制,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) - 与隐式转换相同(

    如果忽略字符串上的额外位不成问题,那么parseIntparseFloat就可以了。 parseInt非常方便,可以指定基数。一元运算符+可用于确保考虑整个字符串。取决于你的选择。 :-)
    就我而言,我倾向于使用这个函数:
    const parseNumber = (str) => str ? +str : NaN;
    

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

    最后,如果你要转换为数字并想知道结果是否为NaN,你可能会尝试做if (convertedValue === NaN)。但那行不通,因为正如Rick在下面指出的那样,涉及NaN的比较始终为false。相反,应该使用if (isNaN(convertedValue))


1
另一个有趣的事实是:如果字符串无法转换为数字,则将其视为 NaNNaN 与任何东西(包括它本身)进行比较都是假的。 因此,所有这些表达式都是假的: 'a' == 5'a' < 5'a' > 5 - Rick Hitchcock
@Bergi - ANDNaN 转换为 0。我今天刚加上这个功能,显然还没有完全清醒。感谢您的提醒!已修复。 - T.J. Crowder

2
MDN关于比较的文档中指出,使用运算符进行比较之前会将操作数转换为公共类型:

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

只有在使用严格比较时才需要应用 parseInt(),因为它不会在比较之前执行自动转换。

0

如果变量是字符串,您应该使用parseInt。添加=以比较datatype值:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接