在聊上述问题前咱们先来讲讲js的数据类型转换,前段时间咱们学习了js中的类型判断,我们知道了如何去判断js中的数据类型,那么,在这么多种数据类型中,它们之间又是如何进行相互转换的呢?今天,小编就带大家来聊一聊js中的数据类型转换。
一、原始值转原始值 ----显示转换
原始值之间的转换(用Boolean、Number、String)
1.原始值转布尔 Boolean(xx)
2.原始值转数字 Number(xx)
3.原始值转字符串 String(xx)
4.原始值转对象 new(xx)
二、对象转原始值:
在js中,当咱们需要将对象转换为原始值的时候,v8引擎则会调用对象的ToPrimitive()
方法来实现
ToPrimitive()
主要作用是将一个JavaScript值转换为原始类型(primitive value),即字符串(String)、数字(Number)、布尔值(Boolean)、null、undefined或Symbol中的任意一种。这一转换过程在某些情况下自动发生,例如当值需要进行数学运算、比较或者作为字符串拼接的一部分时。
具体来说,ToPrimitive()
方法根据上下文可以选择使用哪种转换方式(数值转换或字符串转换):
- 数值上下文(number hint):当值用于数学运算或需要被解释为数值时,比如加减乘除等操作,这时倾向于转换为数值类型。
- 字符串上下文(string hint):当值用于需要字符串表示的场景时,如与字符串相连或作为模板字符串的一部分,这时倾向于转换为字符串类型。
如果被转换的对象是一个对象(而不是原始类型),ToPrimitive()
还会尝试调用对象上的 valueOf()
方法和 toString()
方法(按此顺序),直到得到一个原始值。对象可以通过定义自己的 valueOf()
或 toString()
方法来控制这一转换过程。如果这两个方法都未返回原始值或抛出错误,则会抛出TypeError异常。
这是官方文档给出的说明和解释:
我给大家来解释概括以下ToPrimitive()方法的原理哈:
ToPrimitive()方法规则
如果是想把对象转换为字符串类型则会先执行toString()方法,如果是想把对象转换为数字类型则会先执行valueOf()方法
ToPrimitive(obj,String)==>String(obj)
- 如果接收到的参数是原始值,则直接返回该值
- 否则,调用toString()方法,如果得到原始值,返回
- 否则,调用valueOf()方法,如果得到原始值,返回
- 报错
ToPrimitive(obj,Number)==>String(obj)
- 如果接收到的参数是原始值,则直接返回该值
- 否则,调用valueOf()方法,如果得到原始值,返回
- 否则,调用toString()方法,如果得到原始值,返回
- 报错
我给大家详细说一下toString()方法和value()方法:
toString()方法:
- 所有对象转原始值都会调用toString()
1.{}.toString() 得到由"[object 和 class 和]"组成的字符串
2.[].toString() 返回由数组内部元素以逗号拼接的字符串
3.xx.toString() 返回字符串字面量
valueOf()方法:
——仅限于包装类对象
对象转布尔,一定是ture
let a = {};
let b = [];
if (a) { //Boolean()
console.log('hello');
}
if (b) {
console.log('hello');
}
输出:hello hello
可以看到,if (a)会将a转换为布尔值,Boolean(a),同时b也是,所以对象转布尔值都为true。
隐式转换
在js中,当不同类型的值相互操作时,会发生隐式类型转换。例如,当字符串和数字相加时,js会将数字转换为字符串以进行连接。
一元运算符+
案例一:
分析+"123"
的结果
1.因为前面有一元运算符+,所以先执行ToNumber("123")
2.结果:+123——>123
所以输出结果就是123.
案例二:
分析+[]
的结果:
- 因为前面有一元运算符+,所以先执行ToNumber([]) ,在js官方文档关于ToNumber()的解释是这样的:
2.我给大家解释一下,就是当传入的参数为对象时,也就是表格最后一点,执行ToPerimitive([], Number)
3.根据上面给出的关于ToPerimitive([], Number)的执行步骤,先执行[].valueOf() ,但是valueOf只能只能转换包装类对象(即string、number、boolean),所以执行结果为[]
4.接着执行[].toString(),根据上述给出的结论([].toString() 返回由数组内部元素以逗号拼接的字符串),所以结果为” “
5.+” “就是将''转换为number类型,即Number(''),结果为0
所以输出结果为0.
二元运算符
v1+v2:
1.lprim =ToPrimitive(v1)
2.rprim =ToPrimitive(v2)
3.如果 lprim 或者 rprim 是字符串,那么就ToString(lprim)或者ToString(rprim)再拼接
4.否则,ToNumber(lprim) + ToNumber(rprim)
案例一:
分析1 + '1'
的结果
- lprim = ToPrimitive(1) rprim = ToPrimitive('1')
- ToPrimitive(1):传入的参数为number类型,先调用1.valuoOf(),结果为1(1为number类型,为包装类),所以lprim = 1
- ToPrimitive('1'):传入的参数为string类型,先调用'1'.toString(),结果为'1',所以rprim = '1'
- 因为rprim 是字符串,所以执行ToString(1) + '1'
- '1' + '1' ==> '11',所以结果为'11'
结果:”11“
案例二:
分析null + 1
的结果:
- lprim = ToPrimitive(null) rprim = ToPrimitive(1)
- ToPrimitive(null),根据给出的关于ToPrimitive()的js官方文档,结果为null,所以lprim = null
- ToPrimitive(1):传入的参数为number类型,先调用1.valuoOf(),结果为1(1为number类型,为包装类),所以rprim = 1
- 因为lprim 和 rprim 都不是字符串 ,所以执行ToNumber(null) + ToNumber(1) ,结果为0+1=1
结果:1
案例三
分析 [] + {}
的结果:
- lprim = ToPrimitive([]) rprim = ToPrimitive({})
- 因为此时在两个对象中间有个运算符+,所以执行number类型的步骤,即先执行[].valueOf() + {}.valueOf(),结果为[]和{}
- 接着执行[].toString() + {}.toString,[].toString()的结果为”“, {}.toString的结果为[object Object]
- ""+ '[object Object]' ==> '[object Object]',所以结果为'[object Object]'
结果输出:'[object Object]'
关于 ==
例一:
分析1 == {}
的结果:
- 根据给出的js官方文档,如果一个数为对象,另外一个数为number类型,执行1 == ToPrimitive({})(根据第八点和第九点)
- ToPrimitive({}):有个运算符==,所以执行number类型的步骤,即先执行{}.valueOf() ,结果为{},然后执行{}.toString(),结果为'[object Object]'
- 根据给出的js官方文档,如果一个数为字符串,另外一个数为number类型,执行1 == ToNumber('[object Object]')(根据第四点和第五点)
- ToNumber('[object Object]')的结果为NaN,即结果为 1 == NaN-->false
结果:false
最后咱们就可以来分析一下[] == ![]
的结果:
![]
运算符会将空数组[]
转换为布尔值。在js中,空数组被视为一个真值,原因:[]根据js官方文档,执行ToPrimitive([]),有个运算符==,所以执行number类型的步骤,即先执行[].valueOf() ,结果为[],然后执行[].toString(),所以结果为''- !的执行步骤是先转换为布尔值再取反,Boolean('')为true,所以![]的结果为false
- 即[] == false,此时如果一个操作数是布尔值,另一个操作数不是布尔值,则会将布尔值转换为数字再进行比较。执行[] == ToNumber(false)(根据第六点和第七点),即[] == 0
- 接着执行ToPrimitive([]) == 0(根据第八点和第九点)
ToPrimitive([])
:有个运算符==,所以执行number类型的步骤,即先执行[].valueOf() ,结果为[],然后执行[].toString(),结果为''- 即'' == 0,接着执行ToNumber('') == 0(根据第四点和第五点)
- 即 0 == 0 --> true,所以结果为true
因此最终结果为true.
文章转自:https://juejin.cn/post/7370930879705301011