js类型转换、检测笔记
转换函数
//普通强制类型转换
Number('1');//1
//toNumber规则:true -> 1; undefined -> NaN; null -> 0; {} -> NaN; 对字符串遵循整值转换的规则,处理失败返回NaN
//注意Number会将''、' '、'\n'等空字符串或其他空字符串的组合转换为0
String(1);//"1"
//toString规则:null -> "null"; undefined -> "undefined"; true -> "true"; 1 -> "1"; 普通对象除非自行定义,否则使用内部的toString()(Object.prototype.toString())方法返回内部属性[[Class]]的值
[1,2,3].toString(); //"1,2,3"
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
a.toString(); //"1.07e+21"
数字转各种进制
var t = 60;
t.toString(8); //74
t.toString(16); //3c
Boolean(1);//true
//toBoolean规则:规定了假值包括:undefined,null,false, +0, -0, NaN, ""。其他的都是真值(这里面有例外,后面的假值对象就是特例)。
//封装了假值的对象,说到底还是对象,对象转bool都应该为true
var a = new Boolean(false);
var b = new Number(0);
var c = new String('');
var d = Boolean( a && b && c);//true
//但是和false做值比较时却和false相等
a == false;//true
a === false;//false
//假值对象,转为bool时值为false
Boolean(document.all);//false
隐式强制转换
var a = '20';
var b = 10;
var c = [1,2];
var d = [3,4];
a+b;//"2010"
c+d;//"1,23,4"
+(加法运算符)只能用于数字和字符串(或者说可以转化为数字和字符串的值),如果有一方是字符串,则得到的结果就是字符串(执行字符串拼接)。否则应该为数字或者NaN(执行数字加法)
c对象通过调用其valueOf()无法得到简单的基本类型,于是他转而调用toString()得到了“1,2”
String(c)显式的转换为字符串实际上直接调用toString()方法
例:
var a = {
valueOf: function(){ return 42;},
toString: function(){return 4;}
}
a + "";//"42"
String(a);//'4'
[]+{};//"[object Object]"
解释:{}出现在+运算符中,被作为一个值(空对象来处理),[]和{}都最终调用toString来处理
{}+[];//0
解释:{}被认为是独立代码块(不执行任何操作),代码块结尾不需要分号,没有语法错误。后面的“+[]”被认为是显式的强制类型转换了。
({}+[]);//"[object Object]"
[1,[2,3], {name:'1'}].toString();
//"1,2,3,[object Object]" 数组的toString是对每一个数组元素做toString后的都好拼接
- 是数字运算符,和*与/一样,只能适用于数字,最终都需要转换成数字再运算。
"3.14" - 0;// 3.14
[2] - [1];//1
//隐式转换为布尔值
if/for/while/do while/?:/(||与&&左边的操作数)
//符号的强制转换
var s1 = Symbol();
Boolean(s1);//true
s1 && 1;//1
Number(s1);//语法报错
s1 + 1;//语法报错
String(s1);//"Symbol()"
s1 + '';//语法报错
==表示值相等 ===表示全等(值和类型)
基本类型的==和===结果会有差异
数值、布尔、字符串可以做== ,类型不同时都是转换为数字再做比较 特殊的是数值类型值为NaN不与任何值相等(包括自己) NaN == NaN;//false
null和undefined可以做==
符号类型的值不与其他任何类型的值相等,并且具有唯一性(Symbol() == Symbol();//false)
对象类型(引用类型)==和===比较方式相同
对象和字符串、数字(这里没有说boolean,因为boolean会先转换为数字)的==比较,会先将对象调用toPrimitive抽象操作(先看valueOf看能否得到基本类型,如果不行则使用toString)
42 == [42];//true
var a = {
valueOf: function(){ return 42;},
toString: function(){return 4;}
}
a == 42;//true;
new String('abc') == 'abc';//true, 对象会调用toPrimitive获得基本类型,new String('abc').valueOf();//'abc'
new String('abc') === 'abc';//false
//看一下让人头晕的情况
"0" == false;
false == 0;
"0" == "";
false == "";
false == [];
'' == 0;
'' == [];
'' == {};
0 == [];
"" == [null];
0 == '\n';
//怪异现象
var a = {b:42};
var b = {b:43};
a < b;//false
a == b;//false
a > b;//false
a <= b;//true; 会先判断简单的比较 a > b;然后将结果反转
a >= b;//true 会先判断简单的比较 a < b;然后将结果反转
比较大小
字符串于数字比较,先转换成数字然后再比较,如果不能转换成数字(NaN),则进行字符串比较
'1000' > 300 //true
1000 > '300' //true
'1000' > '300' //false
'1000d' > 300 //false
1000 > '30d' //false
数字检测和转换
isNaN是“检查参数是NaN或不是数字”就返回true,结果是基于Number的转化结果,Number转换是“整体值”转换。parseFloat的转换是“句首有效”转换
'f'/1; //NaN
isNaN('f');//true
isNaN('f'/1);//true
isNaN('1');//false Number('1');//1 parseFloat('1');//1
isNaN("0xf");//false Number("0xf");//15 parseFloat("0xf");//0
isNaN('1f');//true Number('1f');//NaN parseFloat('1f');//1
isNaN('d1');//true Number('d1');//NaN parseFloat('d1');//NaN
isNaN('');//false Number('');//0 parseFloat('');//NaN
isNaN(true);//false Number(true);//1 parseFloat(true);//NaN
isNaN(null);//false Number(null);//0 parseFloat(null);//NaN
isNaN(undefined);//true; Number(undefined);//NaN parseFloat(undefined);//NaN
isNaN({});// true; Number({});//NaN parseFloat({});//NaN
isNaN(Symbol());//语法报错 Number(Symbol());//语法报错 parseFloat(Symbol());//语法报错
//parseFloat只解析10进制,parseInt可以由第二个参数控制进制。
//解析过程是“参数先转换成字符串,然后解析字符串中的数字”
parseInt(1/0, 18);//NaN
parseInt(1/0, 19);//18 过程为:parseInt((1/0).toString(), 19) -> parseInt("Infinity", 19) -> 18;//"I"可以用19进制解析,但是“n”不行
parseInt(new String('42')) -> parseInt(new String('42').toString()) -> parseInt('42') -> 42
parseInt(0.00008) -> parseInt((0.00008).toString()) -> parseInt('0.00008') -> 0
parseInt(parseInt, 16) -> parseInt(parseInt.toString(), 16) -> parseInt("function parseInt() { [native code] }", 16) -> 15
parseInt(false, 16) -> parseInt(false.toString(), 16) -> parseInt("false", 16) -> 250
parseInt('0x10') -> ... -> 16; //没有设置进制的时候默认都是10进制,只有当有“0x”时被识别为16进制,不识别8进制的“0”;这块和Number中字符串转数字一样
parseInt('010') -> ... -> 10;
parseInt(010) -> parseInt((010).toString()) -> parseInt((8).toString()) -> parseInt('8') -> 8
//总结:对字符串的解析,默认只能识别10进制和“0x”的16进制
Number('0x10');//16
Number(0x10);//16
Number('010');//10
Number(010);//8
//js数值
010;//8
0x10;//16
10;//10
Number.isNaN只检测是否是NaN
Number.isNaN('f');//false
Number.isNaN('f'/1);//true;
if(!Number.isNaN){
Number.isNaN = function(n){
return n != n;
}
}
其他
一元运算符 +强制转换为数字
+new Date(); //1545891424614 不推荐使用,使用Date.now()
+"02"; //2
+"-2"; //-2
var a = {b:42, c:"42",d:[1, 2, 3]}
JSON.stringify(a, ['b']);//"{"b":42}"
JSON.stringify(a, function(k, v){if(k !== 'c') return v;});//"{"b":42,"d":[1,2,3]}"
JSON.stringify(a, null, 4);
//缩进4个字符
"{
"b": 42,
"c": "42",
"d": [
1,
2,
3
]
}"