隐形转换
JavaScript中只有在一些极少数的情况下才会因为一个类型错误抛出错误。例如:调用非函数对象或者获取null / underfined的属性时,这就是隐形转换。
首先JS在遇到运算符的时候(-、*、/、%)的时候会将在运算之前把运算符左右两边转换成为数字类型。
原始值 | 转化为数字类型 | 转换为字符串类型 | 转化为Boolean类型 |
false | 0 | ‘false‘ | false |
true | 1 | ‘true‘ | true |
0 | 0 | ‘0‘ | false |
1 | 1 | ‘1‘ | true |
‘0‘ | 0 | ‘0‘ | true |
‘1‘ | 1 | ‘1‘ | true |
NaN | NaN | ‘NaN‘ | false |
Infinity | Infinity | ‘Infinity‘ | true |
-Infinity | -Infinity | ‘-Infinity‘ | true |
‘‘ | 0 | ‘‘ | false |
‘20‘ | 20 | ‘20‘ | true |
"twenty" | NaN | ‘twenty‘ | true |
[] | 0 | ‘‘ | true |
[20] | 20 | ‘20‘ | true |
[10,20] | NaN | ‘10,20‘ | true |
[‘twenty‘] | NaN | ‘twenty‘ | true |
[‘ten‘,‘twenty‘] | NaN | ‘ten,twenty‘ | true |
function(){} | NaN | ‘function(){}‘ | true |
{} | NaN | [object,Object] | true |
null | 0 | ‘null‘ | false |
underfined | NaN | ‘underfined‘ | false |
但是遇到+号时,则会有多种情况
情况1. 运算中含有字符串
1 1+‘2‘ //‘12‘ 2 ‘1‘+2 //‘12‘ 3 1+2+3+‘4‘ //‘54‘
情况2. 运算中不含有字符串
1 1+2+3+4+5 //15
情况3. 运算中含有Bollean值,JS会将Boolean转换为数字,再进行运算。
1 1+true //2
遇到比较运算的时候也会触发隐形转换。
1 if(1==true){ 2 alert(‘true‘); 3 }else{ 4 alert(‘false‘); 5 }
当某个对象出现在了需要原始类型才能进行操作的上下文时,JavaScript 会自动调用 ToPrimitive 函数将对象转化为原始类型,而在ES6后,JS会优先调用对象的[Symbol.toPeimitive]方法来将对象转化为原始类型。
1 var ToPrimitive = function(obj,preferredType){ 2 var APIs={ 3 typeOf:function(obj){ 4 return Object.prototype.toString.call(obj).slice(8,-1); 5 }. 6 //判断是否原始对象的方法 7 isPrimitive:function(obj){ 8 var _this = this, 9 type=[‘Null‘,‘Undefined‘,‘String‘,‘Boolean‘,‘Number‘]; 10 return types.indexOf(_this.typeOf(obj)) !== -1 ; 11 } 12 } ; 13 14 //如果obj本身就是原始对象, 则直接返回 15 if(APIs.isPrimitive(obj)){ return obj; } 16 17 //Date类型会优先调用toString方法,否则优先调用valueOf方法 18 preferredType = ( preferredType === ‘String‘ || 19 APIs.typeOf(obj) === ‘Date‘ ) ? ‘String‘: ‘Number‘; 20 21 if(preferredType === ‘Number‘){ 22 if(APIs.isPrimitive(obj.valueOf())){ return obj.valueOf()}; 23 if(APIs.isPrimitive(obj.toString())){ return obj.toString()}; 24 }else{ 25 if(APIs.isPrimitive(obj.toString())){ return obj.toString()}; 26 if(APIs.isPrimitive(obj.valueOf())){ return obj.valueOf()}; 27 } 28 //否则抛出错误 29 throw new TypeError(‘TypeError‘); 30 }
可以看出转化的本质就是使用toString/valueOf,我们也可以通过覆写的方式来让数值在转换时达到我们理想的结果。
工具类函数JSON.stringify()在将JSON对象序列化为字符串时也是调用了toString。
对于大多数基本数据类型,JSON.stringify()的效果和toSrting基本相同,只不过序列化的结果总是字符串。
1 JSON.stringify(42); //"42" 2 JSON.stringify("66"); //""66"" (含有双引号的字符串) 3 JSON.stringify(null); //"null" 4 JSON.stringify(true); //"true"
JSON.stringify()在对象中遇到underfined、function、symbol时会自动忽略,在数值中遇到则会返回null(保持原来的位置)。
1 JSON.stringify( underfined ); //underfined 2 JSON.stringify(function(){}); //underfined 3 JSON.stringify([1,underfined,3,function(){},4]) //[1,null,3,null,4] 4 JSON.stringify({a:1,b:function(){}}) //{a:1}
显性转换
方法1.使用内建函数
1 String(123); //"123" 2 Number("123“) //123
这里的String是直接调用toString来转换字符串的,与”+“通过ToPrimitive的运作的不一样的。