JavaScript 相等(==)和全等(===)运算符:你真的懂了吗?

75 阅读4分钟

JavaScript 相等(==)和全等(===)运算符:你真的懂了吗?

大家好,这里是你们的前端小伙伴!今天咱们聊聊 JS 里最让人头秃的两个运算符:== 和 ===。别看它俩长得像,实际上一个是"老好人",一个是"铁面无私",一不小心就能把你带进屎山代码的深渊。下面咱们就用最接地气的方式,把这俩货讲明白!


== 和 === 到底有啥区别?

  • ==(相等):会自动进行类型转换,只要值能对上号就算 true。
  • ===(全等):类型和值都得一模一样,绝不含糊。

举个栗子:

1 == '1'    // true,类型不同但值能转成一样
1 === '1'   // false,类型不同直接 false

== 背后的"骚操作"——类型转换底层规则

== 运算符的类型转换其实有一套"祖传秘笈",官方叫"抽象相等比较算法"。简单来说,遇到不同类型时,它会按以下套路来"撮合":

  1. 类型一样,直接比值
  2. null 和 undefined,这俩货==时永远 true。
  3. 字符串和数字,字符串转数字再比。
  4. 布尔值,先转成数字再比。
  5. 对象和原始类型,对象先调用 valueOf/toString 变成原始值。

来个表格,直观感受下:

aba == b说明
nullundefinedtrue祖传兄弟
'0'0true字符串转数字
false0truefalse 转 0
[]''true[] -> ''
[]0true[] -> '' -> 0
[1]1true[1] -> '1' -> 1
[1,2]'1,2'true[1,2] -> '1,2'
{}'[object Object]'false对象转字符串

是不是有点"真是栓Q"?一不小心就掉坑里。

类型转换流程

  1. 类型相同?直接比。
  2. null == undefined?true。
  3. 其中一个是 number?另一个转 number。
  4. 其中一个是 string?string 转 number。
  5. 其中一个是 boolean?boolean 转 number。
  6. 其中一个是对象?对象转原始值。

=== 的"铁面无私"

=== 就很简单粗暴,类型不一样直接 false,绝不含糊:

0 === false      // false
'' === false     // false
null === undefined // false
[] === false     // false

Object.is:新时代的"较真哥"

ES6 新增了 Object.is,用来判断两个值是否"严格相等",但和 === 还是有点区别:

Object.is(NaN, NaN) // true,终于不是 false 了
Object.is(+0, -0)   // false,=== 认为 true
Object.is(0, -0)    // false
Object.is(1, 1)     // true

一般开发用 === 就够了,Object.is 主要用在 polyfill 或底层库里。


深入剖析特殊值的比较

null 和 undefined

null == undefined // true
null === undefined // false

NaN

NaN == NaN // false
NaN === NaN // false
Object.is(NaN, NaN) // true

0、-0、+0

0 === -0 // true
Object.is(0, -0) // false

空字符串、false、0

'' == false // true
0 == '' // true
false == 0 // true

数组、对象和原始类型

[] == '' // true
[] == 0 // true
[1] == 1 // true
[1,2] == '1,2' // true
{} == '[object Object]' // false

真实开发中的"屎山"案例

  1. 表单校验

    if (inputValue == null || inputValue == '') {
      // 以为能判断空,结果 0 也进来了
    }
    

    这样不行啦!0 也会被当成"空",建议用 === 分开判断。

  2. 判断数组是否为空

    if (arr == false) {
      // 空数组也进来了,真是离谱
    }
    

    我们应该 arr.length === 0。

  3. 后端返回数据判断

    if (data == undefined) {
      // null 也会进来
    }
    

    这种情况就把它干掉,建议用 data === undefined。

  4. 布尔值判断

    if (flag == true) {
      // flag 为 1 也会进来
    }
    

    建议直接 if (flag) 或 if (flag === true)。


面试常考陷阱题

来,考考你:

  1. [] == ![] 结果是什么?为啥?

    • 答案:true。
    • 解析:![] 为 false,[] == false,[] 转 '','' == false,'' 转 0,false 转 0,0 == 0,true。
  2. null == 0 结果?

    • 答案:false。
    • 解析:null 只和 undefined 相等。
  3. false == '0' 结果?

    • 答案:true。
    • 解析:'0' 转数字 0,false 转 0,0 == 0。
  4. {} == '[object Object]' 结果?

    • 答案:false。
    • 解析:{} 转 '[object Object]',但类型不同,直接 false。

最佳实践和团队规范建议

  • 能用 === 就别用 ==,团队代码规范直接禁用 ==。
  • 判断 null/undefined 推荐 value == null,其他情况用 ===。
  • 复杂类型比较用 lodash.isEqual 或 JSON.stringify
  • 不要用 == 判断布尔、数字、字符串混合类型
  • 面试遇到 == 相关题,先写出类型转换流程再答,别硬背。

总结

== 就像个"老好人",啥都想撮合一下,结果经常帮倒忙;=== 则是"铁面无私",只认死理。Object.is 更像"较真哥",连 NaN、+0、-0 都分得清清楚楚。开发时,咱们还是多用 ===,少踩坑,别让"屎山代码"毁了你的项目。

如果你觉得有用,记得点赞收藏,这期内容就到这里啦!下期见,拜拜~