【问题标题】:Why does string to number comparison work in Javascript为什么字符串到数字的比较在 Javascript 中起作用
【发布时间】:2015-03-11 18:43:42
【问题描述】:

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

x >= 1 && x <= 999;

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

【问题讨论】:

  • 你不需要 parseInt()。在将数字与字符串进行比较时,JavaScript 会尽可能将字符串转换为数字。

标签: javascript


【解决方案1】:

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

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

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

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

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

如果您决定先显式转换为数字,parseInt 可能是也可能不是您想要的,它不会与隐式转换做同样的事情。以下是选项列表:

  • parseInt(str[, radix]) - 将字符串的开头尽可能多地转换为整数(整数),忽略末尾的多余字符。所以parseInt("10x")10x 被忽略。支持可选的基数(数字基数)参数,因此parseInt("15", 16)2115 十六进制)。如果没有基数,则假定为十进制,除非字符串以 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 的标准数字表示法将 整个 字符串转换为数字(只有数字和小数点 = 小数;@ 987654364@ prefix = hex; 0b = binary [ES2015+]; 0o prefix = octal [ES2015+]; 一些 实现将其扩展为将前导 0 视为八进制,但不严格模式)。 +"10x"NaN,因为 x忽略。 +"10"10+"10.5"10.5+"0x15"21+"0o10"8 [ES2015+],+"0b101" 是 @9876]5438@[ES201+]。有一个问题:+""0,而不是您所期望的 NaN

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

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

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

最后:如果您要转换为数字并想知道结果是否为NaN,您可能会尝试使用if (convertedValue === NaN)。但是那行不通,因为作为 Rick points out below,涉及 NaN 的比较总是错误的。相反,它是if (isNaN(convertedValue))

【讨论】:

  • 另一个有趣的事实:如果字符串不能转换为数字,则将其视为NaNNaN 与任何事物(包括它自己)相比都是错误的。因此,所有这些表达式都是错误的:'a' == 5'a' &lt; 5'a' &gt; 5
  • @Bergi - ANDNaN 转换为0。今天刚刚补充说,显然还没有完全清醒。感谢您标记它!固定。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      相关资源
      最近更新 更多