JS隐形,显性,名义和鸭子类型

隐形转换

  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的运作的不一样的。 

 

posted @ 2021-04-16 10:55  公吧菜腿  阅读(119)  评论(0编辑  收藏  举报