1. == 操作符的强制类型转换规则?
对于 == 来说,如果对比双方的类型不一样,就会进行类型转换。假如对比 x 和 y 是否相同,就会进行如下判断流程:
- 判断两者类型是否相同,相同的话就比较两者的大小;
- 类型不相同的话,就会进行类型转换;
- 判断是否在对比
null和undefined,是的话就会返回true; - 判断两者类型是否为
string和number,是的话就会将字符串转换为number; - 判断其中一方是否为
boolean,是的话就会把boolean转为number再进行判断; - 判断其中一方是否为
object且另一方为string、number或者symbol,是的话就会把object转为原始类型再进行判断;
2. 其他值到字符串的转换规则
Boolean类型,true转换为"true",false转换为"false"。Number类型的值直接转换,不过那些极小和极大的数字会使用指数形式。
let a = 2012312312312321313213123;
let b = 123432
console.log(a.toString()) // '2.0123123123123213e+24'
console.log(b.toString()) // '123432'
Null和Undefined类型 ,null转换为"null",undefined转换为"undefined"。BigInt类型的值直接转换,不过会去掉最后的'n'。
let a = 2012312312312321313213123n
console.log(a.toString()) // '2012312312312321313213123'
Symbol类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误。
let b = Symbol('name')
let c = Symbol('name')
console.log(b.toString()) // 'Symbol(name)'
console.log(c.toString()) // 'Symbol(name)'
- 对普通对象来说,除非自行定义
toString()方法,否则会调用toString()(Object.prototype.toString())来返回内部属性[[Class]]的值,如"[object Object]"。如果对象有自己的toString()方法,字符串化时就会调用该方法并使用其返回值。 例如:
[1,2,3].toString() // '1,2,3'
Object.prototype.toString.call([1,2,3]) // '[object Array]'
3. 其他值到数字值的转换规则?
Undefined类型的值转换为NaN。Null类型的值转换为0。Boolean类型的值,true转换为1,false转换为0。String类型的值转换如同使用Number()函数进行转换,如果包含非数字值则转换为NaN,空字符串为0。Symbol类型的值不能转换为数字,会报错。- 对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
let num1 = undefined
let num2 = null
let num3 = true
let num4 = false
let num5 = '123'
let num6 = '123a'
let num7 = Symbol('num')
console.log(Number(num1)) // NaN
console.log(Number(num2)) // 0
console.log(Number(num3)) // 1
console.log(Number(num4)) // 0
console.log(Number(num5)) // 123
console.log(Number(num6)) // NaN
console.log(Number(num7)) // 报错:Cannot convert a Symbol value to a number
4. object 类型值转为原始类型值
4-1. 转换算法
3种转换算法:偏字符串算法、偏数值算法、无偏算法
4-1-1. 偏字符串算法
首先尝试使用 XX.toString() 方法,如果 XX.toSting() 方法不存在或者返回值不是一个原始类型的值,则尝试使用 XX.valueOf() 方法,如果 XX.valueOf() 仍然无法返回一个原始类型的值,则转换失败,报 TypeError 。
4-1-2. 偏数值算法
偏数值算法与偏字符串算法类似,只不过偏数值算法会先尝试XX.valueOf()方法,再尝试 XX.toString() 方法。
4-1-3. 无偏算法
取决于被转换的对象。如果是一个 Date 对象,则使用偏字符串算法,否则使用偏数值算法。
4-2. XX.tostring() 和 XX.valueOf()
4-2-1. XX.tostring()
XX.tostring()任务是返回对象的字符串表示。
- 普通对象:返回
"[object object]"。 Array类:将每个元素转换为字符串,再用逗号作为分隔符将它们拼接起来。Function类:返回JavaScript源码的字符串。Date类:返回一个人类友好(且JavaScript可解析)的日期和时间字符串。RegExp:返回一个看起来像RegExp字面量的字符串。
4-2-2. XX.valueOf()
把对象转换为可以代表对象的原始类型的值。
- 默认情况下,
XX.valueOf()返回对象本身; Boolean、String、Number这样的包装类定义的valueOf()方法返回被包装的原始值。Date类的实例上的valueOf()方法返回日期的内部表示形式,即:自1970年1月1日至今的毫秒数。
4-3. 转换算法的使用场景
+操作符:如果有一个参数是字符串,则把另一个原始值也转换成字符串,然后进行字符串拼接;否则将两个参数都转换成数值并把它们相加。==和!=:如果一个数值是对象,另一个操作数是原始值,则使用无偏好算法将对象转换为原始值,再进行后续比较。<、<=、>、>=:如果操作数中有一个值是对象,则使用偏数值算法将对象转换成原始值。注意:这个偏数值算法得到的原始值不会再被转换成数值。
5. JavaScript 中如何进行隐式类型转换
在对象转换成基本类型数据时,Date类对象使用偏字符串算法,其他对象使用偏数值算法。
而 JavaScript 中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值转换成基本类型,再进行操作。
以下是基本类型的值在不同操作符的情况下隐式转换的规则:
-
+操作符:+操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。 -
-、*、\操作符:两边先转换为数字再计算(NaN也是一个数字) -
==操作符:操作符两边的值都尽量转成number。 -
<和>:如果两边都是字符串,则比较字母表顺序;其他情况下,转换为数字再比较。