前言
JavaScript中类型转换是一个非常重要的概念,因为JavaScript是一种弱类型或者说动态类型语言,这意味着变量的类型可以在运行时改变。这为开发提供了灵活性,但也可能导致意外的类型转换行为。
原始值转原始值——显示类型转换
通常我们主观使用的转换方式为显示类型转换如,在讲解转换前我们先声明几个数据类型:
let s='s' let n=123 let f=false let u=undefined let un=null
Boolean()- 转换为布尔值
Boolean()
是JavaScript的一个内置构造函数,主要用于将给定的值转换为布尔类型。在JavaScript中,布尔类型只有两个值:true
和 false
。
字符串转布尔类型
console.log(Boolean(s));//true console.log(Boolean(''));//false
在字符串类型中,只有空字符串在转换后会被判定为false,其余的全部会判定为true
数字类型转布尔类型
console.log(Boolean(n));//true console.log(Boolean(0));//false console.log(Boolean(-1));//true console.log(Boolean(Infinity));//true console.log(Boolean(-Infinity));//true console.log(Boolean(NaN));//false
在数字类型中,只有0和NaN转换后会被判定为false,其余的全部会判定为true
Number()- 转换为数字
字符串类型转数字类型
console.log(Number('123'))//123 console.log(Number('abc'))//NaN console.log(Number(''))//0 console.log(Number(' '))//0 console.log(Number('a123'))//NaN console.log(Number('0x00'))//0 十六进制 console.log(Number('0o75')); //61 八进制
当字符串中的字符完全是数字字符时,将自动转为对应的数字,而当尝试将包含非数字字符的字符串(如'abc')转换为数字时,结果是NaN(Not-a-Number),表示该值不能表示一个合法的数字。空字符串和一个只包含空格的字符串在转换为数字时被解释为0,因为没有提供任何数值信息。 字符串'0o'或者是以'0x'开头的,这在JavaScript中是八进制数和十六进制数的标准前缀。当在进行类型转换时,由于数字类型默认为十进制数,检索到'0o'或者是以'0x'开头的字符在符合转换的前提下将被转换为10进制,否则转换为NaN
其他原始类型转数字类型
console.log(Number(true))//1 console.log(Number(false))//0 console.log(Number(undefined))//NaN console.log(Number(null))//0 console.log(Number())//0
对于布尔类型的值转为数字类型true
转为1,false
转为0。因为undefined
表示变量未被赋值,它没有一个具体的数值,因此无法转换成一个有意义的数字。而当尝试将null
转换为数字时,结果是0
。而在JavaScript中,当Number()
函数没有被传递任何值或者传递的是undefined
时,它会返回0
。至于为什么可以查阅es5官方文档Annotated ES5
String()- 转换为字符串
console.log(String(n));//123 console.log(String(0));//0 console.log(String(-1));//-1 console.log(String(Infinity));//Infinity console.log(String(-Infinity));//-Infinity console.log(String(NaN));//NaN console.log(String(undefined));//undefined console.log(String(null));//null
我们可以看到,当使用String()
函数时,它不会改变原始值的类型;它只是返回一个表示原始值的字符串形式。这意味着原始值(如数字、null
、undefined
等)本身的类型和值并未改变
对象转原始值——隐式类型转换
隐式类型转换中,主要探究的就是对象为主的引用数据类型。
引用数据类型- 转Number:Number( { } )
在转换之前,我们要弄清楚Number()函数的运行原理是什么,Number()函数会在一开始先调用内部函数ToNumber(x)
可以看到ToNumber(x)该函数中会调用ToPrimitive()将对象转为原始值,打开ToPrimitive()的解释
我们可以看到对于ToNumber(x)中的ToPrimitive(Object,Number)的执行步骤为:
1.判断接收到的值是不是原始类型,是则返回;
2.调用valueOf()方法,如果得到了原始值则返回
3.调用toString方法,如果得到了原始值则返回
4.报错
实例
console.log(Number({}))//NaN console.log(Number([]))//0 console.log(Number([1]))//1 console.log(Number([1,2]))//NaN
在这几个例子中,都是进行到第三步调用toString方法后返回值变String类型然后对其进行Number()类型转化。
引用数据类型- 转String:String( { } )
同样的在转换之前,我们要弄清楚String()函数的运行原理是什么,String()函数会在一开始先调用内部函数ToString(x)
可以看到ToString(x)该函数中会调用ToPrimitive()将对象转为原始值。因此我们可以看到对于ToString(x)中的ToPrimitive(Object,String)的执行步骤为:
1.判断接收到的值是不是原始类型,是则返回;
2.调用toString方法,如果得到了原始值则返回
3.调用valueOf()方法,如果得到了原始值则返回
4.报错
实例
console.log(String({}))//[object Object] console.log(String([]))//'' 空字串 console.log(String([1]))//'1' console.log(String([1,2]))//'1,2'
为什么ToString(x)中的ToPrimitive()会将toString方法放在前面呢,详细想想,toString对所有原始数据类型都能强制转换,就也不需要valueOf()判断了。
引用数据类型- 转Boolean:Boolean( { } )
任何对象转Boolean都是true,这就不用过多叙述了,看个例子:
console.log(Boolean({}));//true
总结
在ToPrimitive()中的toString方法不是内部方法,而是使用转换目标类型的原型链上的方法
一元操作符 +
会触发隐式类型转换,往Number转
console.log(+'1'); console.log(+'abc'); console.log(+null); console.log(+undefined); console.log(+true); console.log(+false);
二元运算符 +
优先级:字符串>数字
console.log(1+'1'); console.log("1"+1); console.log("1"+true); console.log("1"+null); console.log("1"+undefined); console.log(1+true); console.log(1+null); console.log(1+undefined);
== vs === 的底层机制
== 会触发隐式类型转换而 === 不会触发,这也是为什么[] == ![]
为true的原因。
[] == ![], [] == !true, [] ==false, [] == 0 Number([]) == 0 '' == 0 0 == 0