文章目錄
1. 結論先行
我們都知道,在JS中,要儘量使用全等運算符(“===
”),因爲全等運算符在比較時都不會進行類型的轉化,相對而言速度也會更快。那麼什麼時候使用相等運算符(“==
”)呢?以下兩種情況供參考:
- 用於判斷對象的屬性是否存在
let obj = {};
if( obj.a == null ) {
//這裏相對於:obj.a === null || obj.a === undefined 的簡寫形式,jquery源碼的推薦寫法
}
- 用於判斷函數的參數是否存在
function fn( a, b ) {
if( a == null ) {
//這裏也相當於 a === null || a === undefined 的簡寫
}
}
總結: 一般情況下我們儘量使用“===
”來精確判斷,在判斷對象屬性和函數參數是否存在時可以使用“==
”。
2. 結果判斷參照表
接下來讓我們總結一下各種數據類型使用這兩種運算符所得到的結果,其中:綠色表示結果爲true,白色表示結果爲false
2.1 全等運算符(“===
”)的操作結果
2.2 相等運算符(“==
”)操作結果
2.3 if()條件判斷結果
3. 具體判斷的邏輯說明
(轉載自:js中比較運算符隱式類型轉換)
3.1 全等運算符 (“===
”)
說明: 嚴格匹配,不會類型轉換,必須要數據類型和值完全一致。
先判斷類型,如果類型不是同一類型的話直接爲false;
1 對於基本數據類型(值類型): Number,String,Boolean,Null和Undefined:兩邊的值要一致,才相等
console.log(null === null) // true
console.log(undefined === undefined) // true
注意: NaN: 不會等於任何數,包括它自己
console.log(NaN === NaN) // false
2 對於複雜數據類型(引用類型): Object,Array,Function等:兩邊的引用地址如果一致的話,是相等的
arr1 = [1,2,3];
arr2 = arr1;
console.log(arr1 === arr2) // true
3.2 相等運算符 (“==
”)
非嚴格匹配: 會類型轉換,但是有前提條件一共有五種情況
(接下來的代碼以 x == y 爲示例)
- x和y都是null或undefined:
規則: 沒有隱式類型轉換,無條件返回true
console.log ( null == undefined );//true
console.log ( null == null );//true
console.log ( undefined == undefined );//true
- x或y是NaN : NaN與任何數字都不等
規則:沒有隱式類型轉換,無條件返回false
console.log ( NaN == NaN );//false
- x和y都是string,boolean,number
規則:有隱式類型轉換,會將不是number類型的數據轉成number
console.log ( 1 == true );//true (1) 1 == Number(true)
console.log ( 1 == "true" );//false (1) 1 == Number('true')
console.log ( 1 == ! "true" );//false (1) 1 == !Boolean('true') (2) 1 == !true (3) 1 == false (4)1 == Number(false)
console.log ( 0 == ! "true" );//true
console.log(true == 'true') // false
- x或y是複雜數據類型 : 會先獲取複雜數據類型的原始值之後再左比較
複雜數據類型的原始值: 先調用valueOf方法,然後調用toString方法
valueOf:一般默認返回自身
數組的toString:默認會調用join方法拼接每個元素並且返回拼接後的字符串
console.log ( [].toString () );//空字符串
console.log ( {}.toString () );//[object Object]
注意: 空數組的toString()方法會得到空字符串,
而空對象的toString()方法會得到字符串[object Object] (注意第一個小寫o,第二個大寫O喲)
console.log ( [ 1, 2, 3 ].valueOf().toString());//‘1,2,3’
console.log ( [ 1, 2, 3 ] == "1,2,3" );//true (1)[1,2,3].toString() == '1,2,3' (2)'1,2,3' == '1,2,3'
console.log({} == '[object Object]');//true
- x和y都是複雜數據類型 :
規則只比較地址,如果地址一致則返回true,否則返回false
var arr1 = [10,20,30];
var arr2 = [10,20,30];
var arr3 = arr1;//將arr1的地址拷貝給arr3
console.log ( arr1 == arr2 );//雖然arr1與arr2中的數據是一樣,但是它們兩個不同的地址
console.log ( arr3 == arr1 );//true 兩者地址是一樣
console.log ( [] == [] );//false
console.log ( {} == {} );//false
3.3 經典面試題
注意:八種情況轉boolean得到false: 0 -0 NaN undefined null '' false document.all()
console.log([] == 0); //true
// 分析:(1) [].valueOf().toString() == 0 (2) Number('') == 0 (3) false == 0 (4) 0 == 0
console.log(![] == 0); //true
// 分析: 邏輯非優先級高於關係運算符 ![] = false (空數組轉布爾值得到true)
console.log([] == []); //false
// [] 與右邊邏輯非表達式結果比較
//(1) [] == !Boolean([]) (2) [] == !true (3)[] == false (4) [].toString() == false (5)'' == false (6)Number('0') == Number(false)
console.log([] == ![]); //true
onsole.log({} == {}); //false
// {} 與右邊邏輯非表達式結果比較
//(1){} == !{} (2){} == !true (3){} == false (4){}.toString() == false (5)'[object Object]' == false (6)Number('[object Object]') == false
console.log({} == !{}); //false
3.4 變態面試題
var a = ???
if(a == 1 && a == 2 && a == 3 ){
console.log(1)
}
//如何完善a,使其正確打印1
//答案
var a = {
i : 0, //聲明一個屬性i
valueOf:function ( ) {
return ++a.i; //每調用一次,讓對象a的i屬性自增一次並且返回
}
}
if (a == 1 && a == 2 && a == 3){ //每一次運算時都會調用一次a的valueOf()方法
console.log ( "1" );
}