【JavaScript】全面分析數據類型之間的隱式轉換和大小比較

前言:ECMAScript是鬆散數據類型,也就是說數據類型之間存在着隱式轉換。這種隱式轉換有利也有弊,我們不需要像java,c等強類型語言那樣去強制轉換類型後再去執行不同數據類型之間的操作;但我們也要時刻注意 隱式轉換帶來的陷阱。

一、隱式轉換成Boolean類型

Boolean類型與其他類型之間的轉換在開發中是比較頻繁的用法了。

①、隱式轉換爲true

var str = '123';	    //任何非空字符串(包括'0')
var str2 = '0';
var num = 123;              //任何非零數字值(包括無窮大)
var arr = [];		    //任何對象(包括空數組)(不包括null)
var obj = {};		    //任何對象(包括空數組)(不包括null)
var fn = function(){};      //任何對象(包括空數組)(不包括null)

if(str){//轉換爲true
  console.log(str);	
}
if(str2){//轉換爲true
  console.log(str2);
}
if(num){//轉換爲true
  console.log(num);	
}
if(arr){//轉換爲true
  console.log(arr);	
}
if(obj){//轉換爲true
  console.log(obj);	
}
if(fn){//轉換爲true
  console.log(obj);	
}

②、隱式轉換爲false

var str = '';	       	//空字符串
var num = 0;		//0
var num2 = NaN; 	//NaN
var obj_null = null;    //空對象指針
var undef = undefined;  //undefined 

if(str){//轉換爲false
  console.log(str);	
}
if(num){//轉換爲false
  console.log(num);	
}
if(num2){//轉換爲false
  console.log(num2);	
}
if(obj_null){//轉換爲false
  console.log(obj_null);	
}
if(undef){//轉換爲false
  console.log(undef);	
}

 

二、隱式轉換成String類型

var num = 123;      
var arr = [1,2,3];           
var obj = {};  
var obj_null = null;
var bool_true = true;
var undef = undefined;

console.log(num+'');            //'123'
console.log(arr+'');		//'1,2,3'
console.log(obj+'');		//'[object Object]'
console.log(obj_null+'');	//'null'
console.log(bool_true+'');	//'true'
console.log(undef+'');	        //'undefined'

console.log(5+num);             //128
console.log('5'+num);	   	//'5123'	
console.log('5'+arr);		//'51,2,3'
console.log('5'+obj); 		//'5[object Object]'
console.log('5'+obj_null);  	//'5null'
console.log('5'+bool_true);	   	//'5true'
console.log('5'+undef);	//'5undefined'

可以得到與空字符串和string類型'5'相加,number類型,Boolean類型,null , undefined 都被隱式轉換成string類型,

Array類型和Object類型,都調用了toString()方法,分別轉換成'1,2,3' ,'[object Object]'與String類型'5'進行拼接。

 

三、隱式轉換成數字類型

console.log(100 + '5');       //1005 ->這裏把100轉成了'100',然後進行字符串拼接。
//跟上面做比較   
console.log(100 - '5');       //95   ->這裏把'5'轉成了5,然後執行減法運算。
console.log(100 < '200');     //true ->'200'被轉換成了數字200
console.log(100 == '100');    //true ->'100'被轉換成了數字100
console.log(true+true);	      //2 -> true被轉換成了1
console.log(true == 1);       //true -> true被轉換成了1
console.log(false == 0);      //true -> false被轉換成了0
console.log([] == 0 );	      //true -> Number([]) == 0
console.log([] == false );    //true -> Number([]) = 0; 0==false;
console.log({} >= 0 );	      //false -> Number({})=NaN; 	
console.log({} < 0 );	      //false -> Number({})=NaN;	

這裏要注意的是,上面已經說了 if([]) => 會被轉換成true,而 [] == false,這個[]會被先用Number([])方法轉換成0,然後0 == false 爲真。而{}會被Number({})轉換成NaN。

 

四、不同數據類型之間的大小比較

①、數字類型與其他類型比較

//數字與字符串比較
console.log(100 == '100');      //true('100'被轉換成100 進行比較)
console.log(100 < '200');       //true('200'被轉換成200 進行比較)
console.log(100 < 'a');		//false,都是返回false! ('a'被轉換成NaN了)
console.log(100 < '101a')       //false,都是返回false!
//這裏的'101a'還是被換成了NaN,說明他的轉換機制不是通過parseInt('101a')轉換的,而是通過Number()方法去轉換的。
//帶有非數值的字符串都會被轉換成NaN,這裏要特別需要注意!!

//數字與對象比較
console.log(100 < {});	                //false,都是返回false!
console.log('[object Object]' == {});	//true		
console.log({}.toString());             //'[object Object]'
//{}被調用了toString方法轉換成了'[object Object]'

//數字與數組比較
console.log(1 == [1]);		   //true ([]被調用了toString方法轉換成了'1')
console.log([1].toString());	   //'1'  (string類型)
console.log('1,2' == [1,2] );      //true
console.log([1,2].toString());	   //'1,2' (string類型)
console.log(3 > [1,2])             //false ('1,2'又被轉成NaN了)

//數字與null比較
console.log(0 > null);     //false
console.log(0 == null);	   //false
console.log(0 < null);     //false
console.log(0 >= null);	   //true   !!這是一個很嚴重的bug
//這是一個和嚴重的bug 0>= null 竟然爲true

//數字與undefined比較
console.log(0 > undefined);  //false(都爲false)
console.log(0 == undefined); //false
console.log(0 < undefined);  //false
console.log(0 >= undefined); //false

//數字與boolean比較
console.log(0 == false);   //true
console.log(1 == true);    //true

②、特殊數字類型之間的比較

//NaN之間的比較(NaN不等於NaN)
console.log(NaN >= NaN);   //false
console.log(NaN < NaN);	   //false
console.log(NaN != NaN);   //true
//根據這點,得到NaN跟任何數據類型比較都是false
console.log(!NaN)     //true
//這裏還有一點要注意的,NaN會被隱式轉換爲false,!NaN即爲true

//Infinity之間的比較(Infinity等於Infinity)
console.log(Infinity == Infinity );   //true
console.log(Infinity > -Infinity );   //true

③、string類型之間的比較

console.log('23' > '3');	    	//false  
console.log('2'.charCodeAt(0));		//50
console.log('3'.charCodeAt(0));		//51
//這裏'23'小於'3'這裏要特別注意,比較的是'2','3'的字符編碼

console.log('a' < 'b');			//true	
console.log('a' < 'A');			//false
console.log('A'.charCodeAt(0));		//65
console.log('a'.charCodeAt(0))          //97
console.log('b'.charCodeAt(0));		//98

console.log('你' > '好');		//false
console.log('你'.charCodeAt(0)); 	//20320
console.log('好'.charCodeAt(0));		//22909

//兩個操作數都是字符串,則比較兩個字符串對應的字符編碼值

④、特殊的undefined 和 特殊的null

console.log(null == null);            //true
console.log(undefined == undefined);  //true
console.log(undefined == null);       //true
//undefined,null除了和自身類型相等以外,他們兩個也互相相等

 

五、對象與對象之間的比較

let obj1 = {};
let obj2 = {};
let obj3 = { name:'nick' };
let obj4 = { name:'nick' };
let obj5 = obj3;
let obj6 = obj3;

console.log( obj1 == obj2 );    //false
console.log( obj3 == obj4 );    //false
console.log( obj5 == obj6 );    //true
console.log( obj5 === obj6 );   //true
let arr1 = [];
let arr2 = [];
let arr3 = [1,2];
let arr4 = [1,2];
let arr5 = arr3;
let arr6 = arr3;

console.log( arr1 == arr2 );    //false
console.log( arr3 == arr4 );    //false
console.log( arr5 == arr6 );    //true
console.log( arr5 === arr6 );   //true

對象與對象之間的比較,並不是像上面那樣,隱式調用toString方法轉換後進行比較,而是所處內存空間的比較。(數組屬於特殊對象,同理)。

 

六、特殊數字類型值Infinity運算問題

console.log(Infinity*Infinity);       //Infinity
console.log(Infinity/100);            //Infinity
console.log(100/0);		      //infinity
console.log(Infinity*Infinity);       //Infinity
console.log(0/0);		      //NaN
console.log(Infinity*0);	      //NaN
console.log(Infinity/Infinity);	      //NaN
console.log(100/Infinity);	      //0
//這裏Infinity中的運算要特別注意!!!!!!

 

七、時間大小比較

var oDate1 = new Date(2018,8,8);
var oDate2 = new Date(2018,8,9);
var oDate3 = new Date(2018,9,8);
var oDate4 = new Date(2019,8,8);
console.log(oDate1<oDate2);     //true
console.log(oDate1<oDate3);	//true
console.log(oDate1<oDate4);	//true

var date1 = "2018-08-08";	//"2018/08/08"同理
var date2 = "2018-08-09";	//"2018/08/09"同理
var date3 = "2018-09-08";	//"2018/09/08"同理
var date4 = "2019-08-08";	//"2019/08/08"同理
console.log(date1<date2);       //true
console.log(date1<date3);	//true
console.log(date1<date4);	//true

var time1 = "2018-08-08 08:00:00";
var time2 = "2018-08-08 08:00:01";
var time3 = "2018-08-08 08:01:00";
var time4 = "2018-08-08 09:00:00";
console.log(time1<time2);	//true
console.log(time1<time3);	//true
console.log(time1<time4);	//true

//不同時間格式之間的比較
console.log(oDate1 >= date1);   //false
console.log(oDate1 <= date1);   //false 

console.log(date1 < time1);     //true

 

八、詭異亂碼

console.log(Math.max());        //-Infinity
console.log(Math.min());        //Infinity

console.log([]+[]);	        //''	
console.log((![]).length);	//undefined
console.log(![]+'');	        //'false'	
console.log(![]+[]);		//'false'
console.log(!+![]);	        //true ->布爾類型
console.log(!+[]+![]);	        //1
console.log(!+[]+[]+![]);	//'truefalse'
console.log((!+[]+[]+![]).length);	//9

 

總結:這裏列出了很多不同數據類型之間的操作問題,展現了一些便利,但是也展現了很多的弊端。所以大家要取其精華,去其糟粕,注意這些陷阱。不妨更多的去使用===全等符號。

 

(如有要漏掉內容的麻煩留言告知!)

相關鏈接:

【javsScript】封裝可以分辨所有數據類型的方法

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章