== 和 Toboolean

126 阅读2分钟

==

在转换不同的数据类型时,相等操作符遵循下列基本规则:

  1. 如果有一个操作数是布尔值,则在比较相等性之前,将其转换为数值;

  2. 如果一个操作数是字符串,另一个操作数是数值,在比较之前先将字符串转换为数值;

  3. 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法,用得到的基本类型值按照前面的规则进行比较;

  4. 如果有一个操作数是 NaN,无论另一个操作数是什么,相等操作符都返回 false;

  5. 如果两个操作数都是对象,则比较它们是不是同一个对象。如果指向同一个对象,则相等操作符返回 true;

  6. 在比较相等性之前,不能将 null 和 undefined 转成其他值。

  7. null 和 undefined 是相等的。

总结:如果相等操作符两边的操作数,不包含 null 或者 undefined,且两个操作数不全是对象,在执行相等比较之前,会先调用 Number() 将两个操作数强制转为 Number 类型,然后进行比较

NaN == NaN;  //false (参考第4条规则)
[] == [];    //false
[] == ![];   //true
{} == {};    //false
{} == !{};   //false

在比较 [] == ![] 的时候,先计算 ![] 得到布尔值 false

所以实际上比较的是 [] == false

Number([]) == Number(false);   // ->  0 == 0  ->  true

在比较 {} == !{} 的时候,也是遵守同样的规则:

{} == !{}  ->  {} == false  ->  Number({}) == Number(false)  ->  NaN == 0

ToNumber

  1. null: 转为0
  2. undefined:转为NaN
  3. 字符串:如果是纯数字形式,则转为对应的数字,空字符转为0, 否则一律按转换失败处理,转为NaN
  4. 布尔型:true和false被转为1和0
  5. 数组:数组首先会被转为原始类型,也就是ToPrimitive,然后在根据转换后的原始类型按照上面的规则处理
  6. 对象:同数组的处理
  Number(null) // 0
  Number(undefined) // NaN
  Number('10') // 10
  Number('10a') // NaN
  Number('') // 0 
  Number(true) // 1
  Number(false) // 0
  Number([]) // 0
  Number(['1']) // 1
  Number({}) // NaN

ToBoolean

所以 ToBoolean([]) 被转成 true,!!true 自然是 true 了。 所以这就是 [] == false 而 !![] == true 的真正原因了。这也是为什么我们不能用 if(!array) 来判断空数组而要用 if(array.length === 0) 来判断空数组的原因。