Skip to content

07 相等运算符

== 等于运算符

  • == 运算符被称为宽松相等(loosely equal)或抽象相等运算符。
  • 它用于比较两个操作数是否相等,但在比较过程中会进行类型转换(如果操作数的类型不同)。
javascript
console.log(0 == false) // true,因为 false 转换为 0
console.log('' == false) // true,因为 '' 转换为 0,false 转换为 0
console.log('' == 0) // true,因为 '' 转换为 0
console.log(null == undefined) // true
console.log([1, 2] == '1,2') // true,因为 [1, 2] 转换为 '1,2'
console.log({} == '[object Object]') // false,因为 {} 转换为 '[object Object]' 但两者不同
console.log({} == {}) // false,两个不同的对象引用不相等
console.log(new Date(0) == 0) // true,因为 new Date(0) 转换为 0

console.log(null == 0) // false,因为 null 只与 undefined 相等
console.log(undefined == 0) // false,因为 undefined 只与 null 相等
console.log('0' == 0) // true,因为 '0' 转换为 0
console.log(NaN == NaN) // false,因为 NaN 不等于 NaN

不同类型的比较

  • 如果两个值类型不同,JavaScript 会尝试将它们转换成相同类型后再进行比较。
  • 如果一个值是 null,另一个是 undefined,则它们相等。
  • 如果一个值是数字,另一个是字符串,则将字符串转换为数字进行比较。
  • 如果一个值是布尔类型,则将其转换为数字进行比较:true 转换为 1false 转换为 0
  • 如果一个值是对象,另一个是数字或字符串,则将对象转换为原始值后进行比较。对象转换为原始值是通过调用对象的 valueOf 方法(如果存在)或 toString 方法实现的。
javascript
0 == '0' // true,因为字符串 '0' 被转换为数字 0
0 == [] // true,因为空数组 [] 被转换为数字 0
false == '0' // true,因为布尔值 false 被转换为数字 0,字符串 '0' 被转换为数字 0
null == undefined // true

示例:

  • 布尔值与其他类型比较时,会将布尔值转换为数字:

    javascript
    true == 1 // true,因为 true 转换为 1
    false == 0 // true,因为 false 转换为 0
  • 字符串与数字比较时,会将字符串转换为数字:

    javascript
    '123' == 123 // true,因为 '123' 转换为 123
    '0' == 0 // true,因为 '0' 转换为 0
  • nullundefined 之间相等:

    javascript
    null == undefined // true
  • nullundefined 与其他值比较时不相等:

    javascript
    null == 0 // false
    undefined == 0 // false
    null == '' // false
    undefined == '' // false
  • 对象与基本类型比较时,对象会转换为原始值:

    javascript
    ;([] == ''[(1, 2)]) == // true,因为空数组被转换为空字符串,然后与空字符串比较
      '1,2' // true,因为 [1, 2] 转换为 '1,2'
    ;({}) == '[object Object]' // true,因为 {} 转换为 '[object Object]'
    
    // 比较对象和原始类型
    console.log([1, 2] == '1,2') // true, 因为数组被转换为字符串 '1,2'
    
    // 比较对象引用
    const obj1 = { key: 'value' }
    const obj2 = obj1
    const obj3 = { key: 'value' }
    console.log(obj1 == obj2) // true, 因为它们引用同一个对象
    console.log(obj1 == obj3) // false, 因为它们是不同的对象,即使内容相同

**特殊情况**

  • 空字符串和数字比较时,空字符串会被转换为数字 0
    javascript
    '' == 0 // true,因为 '' 转换为 0
  • NaN 与任何值比较都不相等(包括与 NaN 自身):
    javascript
    NaN == NaN // false

相同类型的比较

  • 如果两个值类型相同,直接进行比较。
  • 对于字符串,比较它们的字符顺序是否一致。
  • 对于数字,比较它们的数值是否相等,注意 NaN 不等于任何值,包括它自己(NaN 不等于 NaN)。
  • 对于布尔值,true 只等于 truefalse 只等于 false
  • 对于对象,比较它们的引用是否指向同一个对象。

=== 严格等于运算符

=== 是一个严格相等操作符,它在比较两个值时,不会进行类型转换,直接比较它们的值和类型。

以下是 === 操作符的比较规则:

  1. 如果两个值的类型不同,则它们不相等。
  2. 如果类型相同,则比较它们的值是否相等。
javascript
0 === '0' // false,因为类型不同,一个是数字,一个是字符串
0 === [] // false,因为类型不同,一个是数字,一个是对象
false === '0' // false,因为类型不同,一个是布尔值,一个是字符串
null === undefined // false,因为虽然它们是相似的,但它们的类型不同
  1. 相同类型的值

    javascript
    1 === 1 // true,因为类型和值都相同
    '1' === '1' // true,因为类型和值都相同
  2. 不同类型的值

    javascript
    1 === '1' // false,因为类型不同,尽管值看起来相同
    true === 1 // false,因为类型不同
  3. null 和 undefined

    javascript
    null === undefined // false,因为类型不同
  4. 对象比较

    javascript
    {} === {}          // false,不同对象,即使内容相同也不相等
    var obj = {};
    obj === obj        // true,比较的是同一个对象引用
  5. NaN

    javascript
    NaN === NaN // false,NaN 与任何值都不相等,包括它自己

== 和 === 的区别

  • ==:相等运算符,比较时会进行类型转换,进行类型转换后再进行比较。
  • ===:全等运算符,比较时会先比较类型,如果类型不同,则直接返回 false,不会进行类型转换。只有当两个操作数的类型和值都相同时,才会返回 true

何时使用 =====

  • 推荐使用 ===:在大多数情况下,使用 === 更为安全和直观,因为它避免了类型转换带来的潜在问题。它确保你比较的值不仅相等,而且类型相同。

  • 特殊情况使用 ==:在少数情况下,当你确实希望进行类型转换后再比较时,可以使用 ==。例如,检查一个变量是否为 nullundefined 时:

    javascript
    // 除了 null 之外,其他都一律用 ===
    
    const obj = { x: 100 }
    if (obj.a == null) {
    }
    // 相当于:
    if (obj.a === null || obj.a === undefined) {
    }
    
    // 原因:使用 == 运算符比较时,null 只与 null 和 undefined 相等。
    // 因此,obj.a == null 等价于 obj.a === null || obj.a === undefined。
    // 如果 obj.a 为 undefined,则 obj.a == null 为 true,因为 undefined == null 为 true

总结

  • == 会进行类型转换后再比较,适用于需要宽松比较的场景。
    • nullundefined 之间相等,但与任何其他值都不相等。
    • NaN 不等于任何值,包括它自己。
  • === 不会进行类型转换,仅在类型和值都相等时才返回 true,适用于需要严格比较的场景。