我正在参加「启航计划」

前言

日常项目开发中,大部分的项目标准会提到运用===代替==,究其原因,无非是相对来讲===的成果是 更可预测 的,相比之下==伴随着隐式类型转化。

两者主要的区别就在于==用于查看 是否持平,而===查看的是 值与类型 是否持平。别小看这简略的两句话,其中伴随的隐式转化可不简略。

举个: 1 == "1" 到底是 1 转化成 "1" 仍是 "1" 转化成1呢?

知其所以然

考虑

求持平运算符的成果总是回来Boolean类型,反映运算符所命名的两个操作数之间的联系是否成立。但,你真的知道 == 的工作原理吗?试着看看以下代码的执行成果

undefined == null; // true
NaN == NaN; // false
1 == "1"; // true
1 == true; // true
2 == true; // false
[] == [] // false
"" == [] // true
0 == [] //true
true == [] // false
true == ![] // false
true == !![] // true
[] == ![] // true
"a" == new String("a"); // true
new String("a") == new String("a"); // false
...

如果你对上面的成果一知半解,或许知道成果可是不知道内部是怎么转化过来的,那么请持续往下看

同类型比较(==)

关于 a == b ;假定两者类型相同

1、 那么当 typeof aundefined,又或许两者皆为null,成果为 true

undeinfed == undefined // true
null == null // true

2、 当typeof astring时,若a、b 是完全相同的字符序列,回来 true

'abc' == 'abc' // true

3、 当typeof anumber时,若 ab 存在1个及以上是 NaN 时,回来 false;不然如果数值持平则为 true,其他状况为 false

123 == 123 // true
NaN == NaN // false

4、 当typeof aboolean时,若a、b 都为 true 或都为 false 时,回来 true;不然回来 false

true == true // true
false == false // true
false == true // false

5、 当typeof aobject时,若a、b 指向同一个目标,回来 true;若 a、b都为 null 回来 true,不然回来 false

{} == {} // false
[] == [] // false,千万不可运用 xxx == [] 来判别数组是否为空
new String("a") == new String("a"); // false
let obj = {}
let a = obj
let b = obj
a == b // true
null == null

不同类型比较(==)(重点)

关于 a == b ;假定两者类型不相同

1、ab 中有一个是undefined,另一个是null时,回来 true

undefined == null // true

2、ab 中有一个是number,一个是string,那么会将string转化为number再进行比较:

1 == '1' // true,转化成 1 == 1进行比较;'1' == 1 同理

3、 ab 傍边存在 boolean时 ,将 boolean 转为number 再进行比较:

1 == true // true,转化成 1 == 1进行比较;
'1' == true // true 转化成 '1' == 1 => 1 == 1
'2' == true // false 
'0' == false // true 

4、ab 中有一个是object(非null),且另一个为根本数据类型 ,则先调用 object的valueOf办法,若成果为根本数据类型,则回来成果进行比较;不然调用object的toString办法,若成果为根本数据类型,则回来成果进行比较,不然抛出过错

// 优先调用valueOf
"a" == new String("a"); // true, new String('a').valueOf() === 'a'
let obj = {
    valueOf(){
        return 2
    }
}
2 == obj // true
// valueOf没有回来根本类型则调用toString
let obj1 = {
    toString(){
        return '3'
    }
}
3 == obj1 // true
// toString没有回来根本类型,报错
let obj2 = {
    toString(){
        return {}
    }
}
3 == obj2 // 报错 Cannot convert object to primitive value
0 == [] // true 转化为 0 == '' => 0 == 0

5、需求注意的是,按照上述第四种状况,会出现一些令人意想不到的状况

true == [] // false,[] 被转化成'' => 0
true == ![] // false, 转化成 true == !true;
true == !![] // true, 转化成 true == !!true;
// 同理
false == [] // true
false == ![] // true
false == !![] // false
[] == ![] // true 本质上是[] == false; 转化为 '' == false  =>  0 == 0  =>  true

这是因为在js中,引证数据类型转化为boolean会被转为true,因而[]加上 ! 之后
会先将[]转为 true,再进行取反,成果就为 false

===

上面提到全等号查看的是 值与类型,那么当两个值类型不一起成果直接为false,若是根本类型且类型相同时则根据本身值是否相同进行判别。需求注意的是:NaN === NaN 成果是 false

若两个值皆为 引证类型,则需求判别两者是否指向同一个目标,是则回来 true,不然为 false

总结

大部分状况下其实运用 == 都是相对安全的,许多状况下也能简化咱们的代码。
容易混杂的主要有以下几种状况(这些状况下如果不行清晰,那么考虑运用===,这关于后续其他开发者来讲也是有利的):

  • 比较的值里面有一边可能是boolean类型(true/false
  • 比较的值里面有一边可能是0''[]

更多时候,如果你能清晰知道你写的代码是你想要的成果以及清晰其中是怎么转化的,那么==号便是安全的!不然请尽量避免运用==,而是运用===

相信看到这儿的你现已对其中的转化规则有了更加深入的了解!更多相关的细节大家可通过 ES5标准 中的11.9.3节进行了解。

写得不对或不好的当地欢迎大家纠正交流~~