背景
最近刷文章一直刷到[]+[] 和 []+![]的面试题,刷某音也刷到了,借助某音老师讲的,留个笔记,记录下对象的隐形转化逻辑,先公布答案 []+[]="" []+![]="false"
对象的隐性转化逻辑
对象的隐性转化逻辑分为三部,按照先后循序依次执行
1:[Symbol.toPrimitive]
首先转化逻辑,先查看是否有 [Symbol.toPrimitive]属性,且这个属性须是一个函数,有此属性的对象,隐性转化先执行此函数,如果此函数返回的不是基础类型,则直接报错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')
2:valueOf
无[Symbol.toPrimitive]属性,则会走valueOf属性转化逻辑,valueOf可以返回基础类型也可不返回基础类型
valueOf返回基础类型
const obj = {
// [Symbol.toPrimitive]:()=>{
// return []
// }
valueOf:()=>{
return "valueOf"
}
}
// obj转化为 "valueOf" +"end"
console.log(obj+'end') // valueOfend
valueOf不返回基础类型,则会走第三步toString
3:toString
前方2个属性都没有,或者valueOf返回的不是基础类型,则会走toString来转义
const obj = {
// [Symbol.toPrimitive]:()=>{
// return []
// }
// valueOf:()=>{
// return []
// }
toString:()=>{
return 'toString'
}
}
console.log(obj+'end') // toStringend
如果toString返回的也不是基础类型,则会报错
const obj = {
// [Symbol.toPrimitive]:()=>{
// return []
// }
// valueOf:()=>{
// return []
// }
toString:()=>{
return []
}
}
console.log(obj+'end')
面试题答案解析
[]+[]解析
基于以上的对象隐性转化逻辑,我们先分析 第一道题 []+[]为何等于""空字符串
我们先看[]+[],会触发对象的隐性转义,我们按照上诉三个步骤,依次看下空数组[]隐性转化成什么
控制台打印可见:[]不存在[Symbol.toPrimitive]属性, valueOf()返回的是[]不是基础类型,所以走第三步 toString()返回空字符串,综上 []+[]等于""空字符串
[]+![]解析
通过第一题我们我们可知 左侧空数组[]转义成空字符串 "", 右侧 ![]如何转化是布尔运算,布尔运算完成后再进行隐性转化 []的布尔运算为 true
此时 ![]进行取反操作为 false 此时上述题目转译成 ""+false结果为字符串 "false"
总结
1:对象的隐性转化顺序,1:[Symbol.toPrimitive] 2:valueOf 3:toString
2:隐性转化优先级低于布尔转化 可查看运算符优先级运算符