引言

首先我们抛出两个问题:

  1. 为什么 [1] == [1]false ?

  2. 为什么 [1] == 1true ?


知识点

如果我们要解决上面的疑问,就需要先搞懂 ===== 的规则和关系

=== 判断规则:

如果 类型 不同,就 不相等

如果两个值都是 数值 ,并且是同一个值,那么 相等 ( ! 例外)

如果两个值都是 字符串 ,每个位置的字符都一样,那么 相等 ,否则 不相等

如果两个值都是 true ,或者都是 false ,那么 相等

如果两个值都是 对象 ,且都引用自 同一个 对象或函数,那么 相等 ,否则 不相等

如果两个值都是 null ,或者都是 undefined ,那么 相等

如果其中至少有一个是 NaN ,那么 不相等

== 判断规则:

如果两个值 类型 相同,进行 === 比较。

如果两个值 类型 不同,他们可能相等。根据下面规则进行类型转换再比较:

如果一个是 null 、一个是 undefined ,那么 相等

如果一个是 字符串 ,一个是 数值 ,把 字符串转换成数值 后再进行比较。

如果任一值是 true ,把它转换成 1 再比较;如果任一值是 false ,把它转换成 0 再比较。

如果一个是 对象 ,另一个是 数值或字符串 ,把 对象转换成基础类型 的值再比较。对象转换成基础类型在第 2 点有提到。

任何其他组合,都 不相等


总结规则

总的来说就是:

对于 === 来说有如下对比规则

  1. 不同类型的值

    如果两个值的类型不同,直接返回 false

  2. 同一类型的原始类型值

    同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回 true,值不同就返回 false

    需要注意的是,NaN 与任何值都不相等(包括自身)。另外,正0 等于 负0

  3. 同一类型的复合类型值

    同一类型的复合类型的值(对象、数组、函数)比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象( 是否为同一引用 )。

  4. undefinednull

    undefinednull自身严格相等,但是两者不严格相等。

对于 == 来说有如下对比规则

  1. 原始类型的值

    原始类型的数据会转换成数值( Number )类型再进行比较。

  2. 对象与原始类型值比较

    如果运算子是对象,会转为原始类型的值,再进行比较。

    「对象」转换成「原始类型」的值,算法是先调用 valueOf() 方法;如果返回的还不是原始类型,再接着调用 toString() 方法,得到原始类型,如果都得不到原始类型,则报错。

    得到原始类型后,按上方的第一点「原始类型的值」进行比较。

  3. undefinednull

    undefinednull 与其他类型的值比较时,结果都为 false,它们互相比较时结果为 true,因为都表示「无」,但两者不「严格相等」,因为本质上还是不一样的,一个是未定义,一个是空。


解决问题

回到第一个问题

为什么 [1] == [1]false ?

答:因为这两个 Array 对象不属于同一个 引用对象 ,所以,这两个数组之间的比较结果为 false

  1. 为什么 [1] == 1true ?

这是因为 [1] 在和 1 进行比较的时候,首先会被转成数字类型,而转成数字类型在实现上又是通过 new Number() 来完成的。

所以,[1] == 1 会变成 Number([1]) == 1

同时,Number 方法接受一个 字符串 作为参数的,也就是 [1].toString() === '1',所以 Number([1]) 相当于写 Number('1'),于是很显然 Number([1]) 就是 1 了。


总结

个人总结:对于相等运算符 == 如果一边是对象,一边是基本类型,JavaScript 会先将对象使用抽象操作 ToPrimitive 将对象转换成基本类型 ( Primitive ) 之后再进行比较,之后就是基本类型之间的比较了。

一个对象转化为基本类型的步骤如下:

  1. 先调用该对象的 valueOf() 方法,如果返回值为 基本类型 ,这个值就是最终值。
  2. 否则,继续调用对象的 toString() 方法,如果返回值为 基本类型 ,这个值就是最终值。
  3. 都无法得到结果的话,抛出异常 Error: Cannot convert object to primitive value

注意:如果对象是 Date 实例,则先执行 toString() 方法

转换为基本类型后,再继续转换为同样类型,之后就是对其进行严格相等运算符 === 的操作啦~


发布时间: 2017-12-03 22:25:48

原始链接: JavaScript 中「相等运算符」和「严格相等运算符」的规则和关系

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。