前言:ECMAScript是松散数据类型,也就是说数据类型之间存在着隐式转换。这种隐式转换有利也有弊,我们不需要像java,c等强类型语言那样去强制转换类型后再去执行不同数据类型之间的操作;但我们也要时刻注意 隐式转换带来的陷阱。
一、隐式转换成Boolean类型
Boolean类型与其他类型之间的转换在开发中是比较频繁的用法了。
①、隐式转换为true
var str = '123'; //任何非空字符串(包括'0',' '空格符)
var str2 = '0';
var str3 = ' '; //空格符
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(str3){//转换为true
console.log(str3);
}
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
//下面这两个比较震惊
console.log( [] == ![] ); //true
console.log( {} == !{} ); //false
对象与对象之间的比较,并不是像上面那样,隐式调用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】封装可以分辨所有数据类型的方法