javascript ==與!=的比較規則(加踩坑)

Novice-XiaoSong發表於2020-11-13

概述: 使用 == 進行比較,當兩個比較元型別不同時,會事先進行型別轉換。(這也是其與 === 的本質區別)
轉換規則:

  1. 當只有一方是 boolean 時,先將 booleannumber。(true: 1, false: 0)
  2. 當一方 number 一方 string 時,stringnumber。(Number(string), 結果可能是 NaN)
  3. 當只有一方是 object 時,object 呼叫 valueOf() 獲取其原始值
    (1)若 valueOf() 方法返回值的型別不是物件(null 除外),則使用該返回值繼續進行 1. 2. 的判斷
    (2)否則,object 呼叫 toString() 獲取其返回值
    (2-1)若toString() 方法返回值的型別不是物件,則使用該返回值繼續進行 1. 2. 的判斷
    (2-2)否則,直接返回 false
    這一部分看不懂的話,可以看看後邊的第一點的示例

比較規則:

  1. undefined == null 為 true
  2. 在與 undefinednull 比較前,另外一個元不會進行型別轉換
  3. 兩個 object 比較時,只有兩個物件相同(也就是其值是同一個指標或者說對同一個物件的引用),== 才會返回 true。例如:{} == {} 返回 false。
  4. NaN 不與任何值相等,包括它自己(NaN == NaN 返回 false)
一、轉換規則3的舉例說明
let o = {};
// eg1:
o.valueOf = () => 1;
o.toString = () => 2;
o == 1;		// true
o == 2;		// false

// eg2:
o.valueOf = () => { return []; }
o.toString = () => 2;
o == 2;		// true
o == [];	// false,這時使用的是比較規則3,兩個物件比較,判斷指標是否相同

// eg3:
o.valueOf = () => { return null; }	// return undefined 也是同樣道理
o.toString = () => 2;
o == 2;		// false valueOf的返回值是null,不是普通物件,直接使用null了。null與2比較返回false
o == null;	// false 此時使用的是比較規則2,object不進行型別轉換

// eg4:
o.valueOf = () => { return []; }
o.toString = () => { return o; }
o == 任何非o的原始型別資料或物件	// false
o == o; 	// true 此時使用的是比較規則3,物件比較判斷是否是同一物件(指標)
二、分析 [] == [] 返回 false,[] == ![] 返回 true
  1. [] == [] 返回 false

    let l1 = [];
    let l2 = [];
    // 因為 l1, l2 實際上是兩個不同的物件(指標),根據比較規則 3 ,返回 false
    
  2. [] == ![] 返回 true

    let l1 = [];
    let l2 = [];
    
    /*	比較步驟
    1. l1 == !l2 ? 
    	!l2 => ![] => false	 (! 優先順序比 == 高) 
    2. l1 == false ?
    	false => 0			 (轉換規則1,一方boolean,boolean轉number)
    3. l1 == 0 ?
    	l1 => l1.valueOf() => [] => (非null物件,不行) => l1.toString() => "" 
    						 (轉換規則3,一方為物件時...)
    4. "" == 0 ?
    	"" => 0				 (轉換規則2,一方number一方string,string轉number)
    5. 0 == 0 ,返回true
    */
    
二、分析 {} == {}{} == !{} 均返回 false
  1. {} == {} 返回 false

    let o1 = {};
    let o2 = {};
    // 因為 o1, o2 實際上是兩個不同的物件(指標),根據比較規則 3 ,返回 false
    
  2. {} == !{} 返回 false

    let o1 = {};
    let o2 = {};
    
    /* 比較步驟
    1. o1 == !o2 ?
    	!o2 => !{} => false		(! 優先順序比 == 高) 
    2. o1 == false ?
    	false => 0				(轉換規則1,一方boolean,boolean轉number)
    3. o1 == 0 ?
    	o1 => o1.valueOf() => {} => ({}是物件,不行) => o1.toString() => '[object object]'
    							(轉換規則3,一方為物件時...)
    4. '[object object]' == 0 ?
    	'[object object]'  => NaN
    							(轉換規則2,一方number一方string,string轉number)
    5. NaN == 0 返回 false		(比較規則4,NaN不與任何值相等)
    */
    

==, ===, 與Object.is()的區別

相關文章