对象的隐性转化逻辑:Symbol.toPrimitive → valueOf → toString
最近刷文章一直刷到 []+[] 和 []+![] 的面试题,刷某音也刷到了,借助某音老师讲的,留个笔记,记录下对象的隐性转化逻辑。先公布答案:
[]+[] === "",[]+![] === "false"对象的隐性转化逻辑分为三步,按照先后顺序依次执行:
| 步骤 | 方法 | 说明 |
|---|---|---|
| 1 | [Symbol.toPrimitive] | 先查看是否有该属性,且该属性须是一个函数;有此属性的对象,隐性转化先执行此函数 |
| 2 | valueOf | 无 [Symbol.toPrimitive] 属性,则走 valueOf 转化逻辑 |
| 3 | toString | 前两步都没有,或 valueOf 返回的不是基础类型,则走 toString 转义 |
有此属性的对象,隐性转化先执行此函数。如果此函数返回的不是基础类型,则直接报错 TypeError: Cannot convert object to primitive value。
[Symbol.toPrimitive] 返回基础类型,obj+'end' 触发隐性转化:
const obj = {
[Symbol.toPrimitive]:()=>{
return "toPrimitive"
}
}
// obj转化为 "toPrimitive" +"end"
console.log(obj+'end') // toPrimitiveend
[Symbol.toPrimitive] 返回非基础类型,则直接报错:
const obj = {
[Symbol.toPrimitive]:()=>{
return []
}
}
console.log(obj+'end') // TypeError: Cannot convert object to primitive value
无 [Symbol.toPrimitive] 属性,则会走 valueOf 属性转化逻辑。valueOf 可以返回基础类型,也可以不返回基础类型。
valueOf 返回基础类型:
const obj = {
valueOf:()=>{
return "valueOf"
}
}
// obj转化为 "valueOf" +"end"
console.log(obj+'end') // valueOfend
前两步都没有,或者 valueOf 返回的不是基础类型,则会走 toString 来转义。
const obj = {
toString:()=>{
return 'toString'
}
}
console.log(obj+'end') // toStringend
const obj = {
toString:()=>{
return []
}
}
console.log(obj+'end') // TypeError: Cannot convert object to primitive value
基于以上的对象隐性转化逻辑,我们先分析第一道题:[]+[] 为何等于 "" 空字符串。
我们先看 []+[],会触发对象的隐性转义。按照上述三个步骤,依次看下空数组 [] 隐性转化成什么:
[]+[] 等于 "" 空字符串。通过第一题可知:左侧空数组 [] 转义成空字符串 ""。右侧 ![] 如何转化?
布尔运算完成后再进行隐性转化:[] 的布尔运算为 true,此时 ![] 进行取反操作为 false,上述题目转译成 "" + false,结果为字符串 "false"。
[]+![] 等于 "false"。