== 和 === 有什么区别

== 和 === 运算符用于比较两个值是否相等,当然,它们对相等的定义不尽相同。两个运算符允许任意类型的操作数,如果操作数相等则返回true,否则返回false。那么关于== 和===有什么区别呢?让我们一起来探究。

‘===’恒等

===严格相等运算符,首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换:
如果两个类型不相同,则它们不相等。例如:

1
1 === 'true'  // false

如果两个值都是null或者都是undefined,则它们相等。例如:

1
null === undefined  // false

如果两个值都是布尔值true或者都是false,则它们相等。例如:

1
true === true   // true

如果其中一个值是NaN,或者两个值都是NaN,则它们不相等。(NaN和其他任何值都是不相等的,包括它本身。通过x!==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式的值才为true。例如:

1
2
NaN === NaN   // false
NaN !== NaN // true

如果两个引用值指向同一对象,数组或函数,则它们是相等的。如果指向不同的对象,则它们是不相等的,尽管两个对象具有完全一样的属性。例如:

1
2
3
4
5
var obj = {};
obj === obj ; // true
var obj1 = {a:1};
var obj2 = {a:1};
obj1 === obj2; // false

如果两个值类型相等,值不相等,那么它们不相等。例如:

1
2
3
4
true === false;  //  false
"1" === "8" // false

...

如果两个值相等,类型相等,那么它们相等。例如:

1
2
3
4
5
6
7
8
"1"==="1";  //  true
8 === 8; // true
"true" === "true"; // true
false === false;
undefined === undefined; // true
null === null; // true

...

‘==’相等

相等运算符“==”和恒等运算符相似,但相等运算符但比较并不严格。如果两个操作数不是同一类型,那么相等运算符会尝试进行一些类型转换,然后进行比较。例如:

如果两个值类型相同,但值不同,那么它们不相等。

1
2
3
4
5
"1" == "3";  //  false
"true" == "false"; // false
false == true // false

...

如果一个值是null,一个值是undefined,则它们相等。例如:

1
null == undefined  //  true

如果其中一个是布尔值,则将其转换为数字,true 转换为 1,false 转换为 0,然后再进比较。例如:

1
2
3
1 == true;  //  true
false == 0 // true
true == false // false

如果其中一个是数字,一个是字符串,先将字符串转为数字,然后再使用转换后的值进行比较。例如:

1
2
1 == "1"  //  true
"500" == 800 // false

如果一个值是对象,另一个值是数字或字符串,则需将对象转换为原始值(通过toString()或valueOf().js中的内置类首先尝试使用valueOf(),再进行toString(),日期类除外,日期只使用toString() ),然后再进行比较。

1
2
3
var obj ={a:"b"};
obj.toString(); // "[object Object]"
1 == obj; // false

如果两个对象的类型相同,但引用地址不同,那么它们不相等。例如:

1
2
[] == []  //  false
{} == {} // false

由此可见两者的区别:

=== 不需要进行类型转换,只有类型相同并且值相等时,才返回 true.
== 如果两者类型不同,首先需要进行类型转换。具体流程如下:
首先判断两者类型是否相同,如果相等,判断值是否相等;
如果类型不同,进行类型转换;
判断比较的是否是 null 或者是 undefined, 如果是, 返回 true;
判断两者类型是否为 string 和 number, 如果是, 将字符串转换成 number;
判断其中一方是否为 boolean, 如果是, 将 boolean 转为 number 再进行判断;
判断其中一方是否为 object 且另一方为 string、number 或者 symbol , 如果是, 将 object 转为原始类型再进行判断。

1
2
3
4
5
6
let dabao = {
age: 25
}
let baojie = dabao;
baojie.gae = 20;
console.log(dabao === baojie); //true, 注意复杂数据类型,比较的是引用地址

下面分享一个有意思的面试题:

例如:[] == ![] // true

这个为什么是true呢?

首先,我们需要知道 ! 优先级是高于 == (更多运算符优先级可查看: 运算符优先级) 所以先算右边,![] 结果为 false,[] == ![] 等同于=> [] == false;

然后进行类型转换,转为原始类型:[] == false 等同于=> “” == false;

再进行类型转换,转为数字:”” == false 等同于=> 0 == 0 此时类型相同,比较值:
0 == 0 // true值相等,所以结果为true;