# 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
:::
#### 問題五:

:::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
:::