---
# System prepended metadata

title: The Difference between ==(相等)and ===(全等)

---



# The Difference between ==(相等)and ===(全等)

### “＝” 一個等號很單純，就是指定、賦予值。
` let a = 3;` 將等號右手邊的值指定到a變數中。
### == vs ===
==  一般相等比較 Abstract Equality Comparison ("loose equality", "double equals")
* 先強制轉型後比較

=== 嚴格相等比較Strict Equality Comparison ("strict equality", "identity", "triple equals")
* 不會強制轉型

### type conversion (coercion)  強制轉型
分為兩種

1.「明確的」強制轉型（explicit coercion），有明確的刻意寫出轉換型別的動作。
 例如： ToString、ToNumber、ToBoolean 等等。。
2.「隱含的」強制轉型（implicit coercion），沒有明確指出要轉換型別但卻轉型的動作。
```javascript=
var a = 42;
var b = String(a); // 明確的強制轉型
var c = a + ''; // 隱含的強制轉型

b; // '42'
c; // '42'
```
### 「隱含的」強制轉型狀況？
1. “+” 運算子
當其中一方是字串時,+就是字串的串接運算子。會將另一方強制轉值為字串。
```javascript=
const a = '1';
const b = 1;
const c = [1, 2];
const d = [3, 4];

a + 1; // "11"
b + 1; // 2
b + ''; // "1"
c + d; // "1,23,4" 
//陣列 c 和 d 分別會使用 toString 轉為 '1, 2' 與 '3, 4'。
```
2. 使用數學運算子將字串轉為數字(除了＋號)
```javascript=
const a = '1';

a + 1; // "11"
a - 0; // 1 數字
a * 1; // 1 數字
a / 1; // 1 數字

```
3. 隱含的強制轉換為Boolean值
    * 條件判斷(if/for/while)
    * 三元運算是 a=b?c:d
    * 邏輯運算子 || or && and 
```javascript=
var a = 12345;
var b = 'Hello World';
var c; // undefined
var d = null;

if (a) {
  // true
  console.log('a 是真的'); // a 是真的
}

while (c) {
  // false
  console.log("c ");
}

c = d ? a : b;
console,log(c) //'Hello World'

if ((a && b) || c) {
  // true
  console.log('結果是真的'); // 結果是真的
}
```
補充：運算子 || 與 && ( 短路求值 short circuiting)更短更簡潔的判斷式

*  OR operator ||  short circuiting
假如值是truthy value，他會直接回傳那個truthy value
假如都沒有truthy value，就會回傳比較中的最後一個值
```javascript=
console.log(3 || 'Jonas'); //3
console.log('' || 'Jonas');//Jonas
console.log(true || 0);//true
console.log(undefined || null|| 0); //0
console.log(undefined || 0 || '' || 'hello' || 23 || null); //hello
```
實作：可以用來設定預設值
`const guest = name.firstName || name.secondName  || 'anonymous'; `
* AND operator &&  short circuiting
它跟OR operator的作用相反。
假如值是falsy value，他會直接回傳那個falsy value
假如都沒有falsy value，就會回傳比較中的最後一個值
```javascript=
console.log(0 && 'jonas'); //0
console.log('' && 'jonas'); //''
console.log(7 && 'jonas'); //jonas
console.log('hello' && 23 && null && 'jonas'); //null
console.log('hello' && 23 && {} && 'jonas'); //'jonas'
```
* 補充：The Nullish Coalescing Operator 空合併運算子
幾乎跟OR operator一樣， 但只有null and undefined會被當成falsy value也就是Nullish value
```javascript=
console.log(0 || 10) //10
console.log(0 ?? 10); //0
console.log(undefined ?? 10); //10
console.log(undefined ?? 10 ?? 'hello'); //10
console.log(undefined ??null?? ''  ?? 0 ??'hello' ?? 23) // ''
```
## 規則要注意的點：
#### 如果型別相同，就會以同一性做比較，但要注意
* NaN 不等於任何值包括自己。不管是 == 或是 ===
* +0、-0 彼此相等。不管是 == 或是 ===
* 物件(object、array、function)的相等是比較參考（reference），若指向同一個參考才是相等。
```javascript=
var a = {weather : "sunny"};
var b;
b = a;
console.log(a)      //sunny
console.log(b)      //sunny
b === a             //true
```
#### 如果型別不同，則會先將其中一個或兩個值先做強制轉型,再用型別相同的同一性做比較。
* 字串與數字做比較下，字串會透過Number()嘗試轉型為數字。
* 如果其中一個為布林值，會將true轉為1,false轉為0,布林值轉為數字。
* null 與 undefined 在寬鬆相等( == )下會強制轉型為彼此，因此是相等的，但不等於其他值。在嚴格相等比較( === )時undefined等於自己，null也只等於自己。
* 若比較的對象是物件，使用 valueOf()（優先）或 toString() 將物件取得基本型別的值，再做比較。



## 結論
寬鬆相等（Loose Equals） vs 嚴格相等（Strict Equals）
關於相等性的運算子有四個
「 == 」（寬鬆相等性 loose equality）、
「 === 」（嚴格相等性 strict equality）、
「!=」（寬鬆不相等 loose not-equality）和
「 !== 」（嚴格不相等 strict not-equality）。
=="很多人會説  == 與 === 的差異在於 ， === 會做型別檢查而 == 不會，這樣的說法不夠準確，要說 ， == 與 === 的差異在於是否會做強制轉型， == 會做強制轉型，而 ===  不會。"==

參考連結：
[你懂 JavaScript 嗎？#8 強制轉型（Coercion）](https://cythilya.github.io/2018/10/15/coercion/)
[js真值表](https://thomas-yang.me/projects/oh-my-dear-js/)
[Web開發學習筆記02 — 等號比較運算子(Equality operators) “==” vs. “===”](https://teagan-hsu.coderbridge.io/2020/10/17/equality-operators/)

## 問答補充：
#### 問題一：
```javascript=
const a = '123';
const b = 123;

a === b; // 答案是？
a == b; // 答案是？
```
:::spoiler answer
a === b; // false
a == b; // true
:::


#### 問題二：
```javascript=
const a = true;
const b = 123;

a === b; // 答案是？
a == b; // 答案是？
```

 :::spoiler answer
a === b; // false
a == b; // false
:::


#### 問題三：
```javascript=
const a = null;
const b = 123;

a === b; // 答案是？
a == b; // 答案是？
```
 :::spoiler answer
a === b; // false
a == b; // false
:::

 


#### 問題四：
```javascript=
const a = '1,2,3';
const b = [1, 2, 3];

a === b; // 答案是？
a == b; // 答案是？
```
 :::spoiler answer
a === b; // false
a == b; // true
:::

 

#### 問題五：
![](https://i.imgur.com/SKM6bZ3.jpg)

 :::spoiler answer
因為String轉換成Number，故0 == 0
0 == "0"      //true
因為empty array(object type)轉為empty string(primitive type)，故[]轉變成""，而""是String再轉換為Number，故""為0，最後0 == 0成立！
0 == []       //true
按照的解釋，[]轉為""(String)，"0"與""皆為String，所以Javascript不會再強制轉換類型了，故"0" != []
"0" == []     //false
:::




#### 終極問答：
```javascript=
'0' == false; 
false == 0; 
false == ''; 
false == []; 
false == {}; 

'' == 0; 
'' == []; 
'' == {}; 

0 == [];
0 == {};

[] == ![];

2 == [2];
'' == [null];
0 == '\n';
```
 :::spoiler answer
 
"0" == false;，true，字串轉數字、布林再轉數字
false == 0;，true，布林轉數字
false == "";，true，字串轉數字、布林再轉數字
false == [];，true，布林轉數字、陣列取 toString 得到空字串再轉數字
false == {};， false，布林轉數字、物件取 valueOf 得到空物件
"" == 0;，true，字串轉數字
"" == [];，true，字串轉數字、陣列取 toString 得到空字串再轉數字
"" == {};，false，字串轉數字、物件取 valueOf 得到空物件
0 == [];，true，陣列取 toString 得到空字串再轉數字
0 == {};，false，物件取 valueOf 得到空物件
[] == ![]，true，左手邊取 valueOf 得到空字串再轉數字得到 0，右手邊被 ! 強制轉為布林得到 false 再轉為數字
2 == [2]，true，陣列取 toString 得到字串 ‘2’ 再轉數字
"" == [null]，true，陣列取 toString 得到空字串，轉數字後得到 0
0 == '\n'，true，’\n’ 意即 ‘ ‘（空白），轉數字後得到 0
:::


