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

IT技术 javascript
2021-02-01 20:52:55

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

x >= 1 && x <= 999;

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

3个回答

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

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

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

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

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

如果你决定明确转换为数字第一,parseInt可能是也可能不是你想要什么,它不会做同样的事情,隐式转换。以下是选项的概要:

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

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

  • parseFloat(str)- 类似parseInt,但可以处理浮点数并且只支持十进制。再串上多余的字符被忽略,所以parseFloat("10.5x")10.5(将x被忽略)。由于仅支持十进制,parseFloat("0x15")is 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位的整数(转换和数字NaN0如果字符串不能被转换为有效的数)。

因此,如果可以忽略字符串上的额外位,parseInt或者没问题parseFloatparseInt对于指定基数非常方便。一元+对于确保考虑整个字符串很有用接受你的选择。:-)

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

另一个有趣的事实:如果字符串不能转换为数字,则将其视为NaN. NaN与任何事物(包括其自身)相比都是错误的。因此,所有这些表达式都是错误的: 'a' == 5, 'a' < 5,'a' > 5
2021-03-23 20:52:55
@Bergi - AND转换NaN0. 今天刚刚补充说,显然还没有完全清醒。感谢您标记它!固定的。
2021-04-04 20:52:55

MDN对比较文档指出,操作数比较(与您正在使用的运营商)之前转换为通用类型:

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

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

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

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