先记住这个答案
== 遇到一边是字符串、一边是数字,会对字符串执行内部的 ToNumber 操作,转成数字后再比较。这个转换和 Number() 函数的行为一致:要求整段文本都是合法数值,空字符串和纯空白返回 0,包含非数字字符的返回 NaN。因为 NaN 和任何值比较都是 false,字符串里只要混了无法解析的字符,== 就一定不成立。
- 字符串比较时用
ToNumber转换 - 空字符串和纯空白都转成
0 - 转不了的变
NaN,比较必定false ===类型不同直接false,无转换
ToNumber 转换结果和你想的可能不一样
很多人第一反应是 == 会像 parseInt 那样解析字符串,但两者差异很大。parseInt 从左往右扫,遇到非数字字符就停下来,能取到前缀部分的数字。ToNumber 不一样,整段文本必须都是合法数值,多出一个字母就直接返回 NaN。
Number() 转换和 == 结果JavaScriptconsole.log(Number('42'), '42' == 42);
console.log(Number(''), '' == 0);
console.log(Number(' '), ' ' == 0);
console.log(Number('10px'), '10px' == 10);
console.log(Number('0x10'), '0x10' == 16);
console.log(Number('1e3'), '1e3' == 1000);查看输出与解释
42 true
0 true
0 true
NaN false
16 true
1000 true'10px' 用 parseInt 能拿到 10,但 ToNumber 认为它不是完整数字文本,直接返回 NaN,所以 '10px' == 10 是 false。'0x10' 是合法的十六进制,转成 16 后和 16 相等。'1e3' 是指数表示法,转成 1000。
空字符串和纯空白都转成 0,这是最容易踩坑的地方。表单里拿到的输入值通常是字符串,如果直接写 inputValue == 0,用户什么都没填也会匹配到 0。正确做法是先检查非空,再用 Number() 显式转换,或者直接用 === 比较。
布尔值碰上字符串会多一步转换
如果 == 的某一边是布尔值,引擎会先把布尔转成数字——true 变 1,false 变 0——然后再走字符串转数字的流程。这会产生一些反直觉的结果。
'2' == true 为什么是 falseJavaScriptconsole.log('0' == false);
console.log('' == false);
console.log('1' == true);
console.log('2' == true);查看输出与解释
true
true
true
false'2' == true 的转换过程是这样的:先把 true 转成 1,然后把 '2' 转成 2,最后比较 2 == 1,结果是 false。这说明 == 不是在判断一个值"是否为真",它走的是一套固定的类型转换规则。如果想判断一个值在逻辑上是否为真,应该直接写 if (value) 或者用 Boolean(value)。
同理 '0' == false 是 true,因为 false 变成 0,'0' 也变成 0。但 '0' 在 if 里是真值(非空字符串),这两种判断方式的结果完全相反。这就是 == 让人困惑的原因——表达式看起来在问"是不是假的",实际上在做数字比较。
容易答错的地方
- 以为
parseInt和ToNumber的规则一样 parseInt('10px')返回10,因为它遇到p就停下来了。但'10px' == 10是false,因为==用的是ToNumber,要求整段文本合法。面试里提到字符串转数字时,一定要说清楚是哪种转换方式。- 用
value == NaN检查转换是否失败 NaN和任何值都不相等,包括它自己。所以value == NaN永远返回false,无论value是什么。正确的做法是用Number.isNaN()检查,它不会对参数做隐式转换,只在参数真的是NaN时才返回true。
面试官还会怎么问?
为什么 '' == 0 是 true 但 '' === 0 是 false?
=== 不做任何类型转换,字符串和数字类型不同直接返回 false。== 先把空字符串转成 0,再比较 0 == 0,所以是 true。这就是推荐默认使用 === 的原因——它不会产生意外的隐式转换。
有没有什么场景适合用 ==?
value == null 是个被广泛认可的惯用法,可以同时匹配 null 和 undefined,省去写 value === null || value === undefined 的麻烦。除此之外,几乎所有团队都建议用 ===,ESLint 的 eqeqeq 规则也是默认开启的。
Number() 和 + 前缀的转换结果一样吗?
一样。+value 就是 Number(value) 的简写,走的都是 ToNumber。比如 +'' 返回 0,+'10px' 返回 NaN。区别只在可读性上,显式写 Number() 意图更明确。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。