本文涉及的参考资料均在JavaScript数据结构学习与实践数据索引中声明。隐式类型转换在JavaScript中,当我们进行比较运算或加减乘除四种算术运算时,往往会触发JavaScript的隐式类型转换机制;这部分经常令人困惑。例如,浏览器中的console.log操作通常是将任意值转换成字符串再显示,而数学运算则是先将值转换成数字类型(Date类型对象除外)再进行操作。我们先来看看JavaScript中运算符运算的一些典型结果,希望看完这一部分后,能对每一项给出合理的解释://Compare[]==![]//trueNaN!==NaN//true1==true//true2==true//false"2"==true//flasenull>0//falsenull<0//falsenull==0//falsenull>=0//true//加法true+1//1undefined+1//NaNletobj={};{}+1//1,其中{}被视为一个代码块{1+1}+1//1obj+1//[objectObject]1{}+{}//Chrome显示“[objectObject][objectObject]”,Firefox显示NaN[]+{}//[objectObject][]+a//[objectObject]+[]//相当于+""=>0{}+[]//0a+[]//[objectObject][2,3]+[1,2]//'2,31,2'[2]+1//'21'[2]+(-1)//"2-1"//减法或其他操作,不能进行字符串拼接,所以返回NaN[2]-1//1[2,3]-字符串格式错误1//NaN{}-1//-1基本类型之间的转换我们在JavaScript中常说的基本类型包括数值类型、字符串类型、布尔类型、空类型;转换函数为String、Number和Boolean//Stringletvalue=true;console.log(typeofvalue);//booleanvalue=String(value);//nowvalueisastring"true"console.log(typeofvalue);//string//Numberletstr="123";console.log(typeofstr);//stringletnum=Number(str);//变成number123console.log(typeofnum);//numberlettage=Number("anarbitrarystringinsteadofanumber");console.log(age);//NaN,conversionfailed//Booleanconsole.log(Boolean(1));//trueconsole.log(Boolean(0));//falseconsole.log(Boolean("hello"));//trueconsole.log(Boolean(""));//false最后,我们可以得到如下JavaScript原始类型转换表(包括复合类型到原始类型转换的例子):在比较运算和加法运算中,涉及到将运算符两边的运算对象转换为原对象的步骤;在JavaScript中,这种转换实际上是由ToPrimitive函数执行的实际上,当一个对象出现在需要原始类型进行操作的上下文中时,JavaScript会自动调用ToPrimitive函数将对象转换为原始类型;这是一个典型的场景。这个函数的签名如下:ToPrimitive(input,PreferredType?)为了更好的理解它的工作原理,我们可以简单的用JavaScript实现:varToPrimitive=function(obj,preferredType){varAPIs={typeOf:function(obj){returnObject.prototype.toString.call(obj).slice(8,-1);},isPrimitive:function(obj){var_this=this,types=['Null','Undefined','String','Boolean','Number'];returntypes.indexOf(_this.typeOf(obj))!==-1;}};//如果obj本身已经是原始对象,则直接返回if(APIs.isPrimitive(obj)){returnobj;}//对于Date类型,会优先使用它的toString方法;否则,valueOf方法preferredType=(preferredType==='String'||APIs.typeOf(obj)==='Date')?'String':'Number';if(preferredType==='Number'){if(APIs.isPrimitive(obj.valueOf())){returnobj.valueOf()};if(APIs.isPrimitive(obj.toString())){returnobj.toString()};}else{if(APIs.isPrimitive(obj.toString())){returnobj.toString()};if(APIs.isPrimitive(obj.valueOf())){returnobj.valueOf()};}thrownewTypeError('TypeError');}我们可以简单地覆盖一对对象的valueOf方法,可以发现运算结果发生了变化:letobj={valueOf:()=>{return0;}}obj+1//1如果我们强制一个对象的valueOf和toString方法是overwritten如果返回值是对象,会直接抛出异常log("toString");return{};//notaprimitive}}obj+1//errorUncaughtTypeError:Cannotconvertobjecttoprimitivevalueat
