面试题 {} + [], [] + {} 以及隐式数据类型转换

193 阅读2分钟

(+) 运算符

  • 一元运算的时候等同于调用 Number() 方法 好像是ES7语法
    +'10' // 10  
    Number('10') // 10
    
  • 二元运算时如果两个值中间有 String 类型那么就会做字符串拼接 如果都是 Number 类型就做运算符
    '10' + 10 // '1010'
     10 + 10 // 20
     'Hello ' + ' ' +'world' // Hello world
    

隐式数据转换

  • 以引用数据类型转原始值为例
  1. 先检查 Symbol.toPrimitive 存不存在 (内置的Symvbol的值。作为对象的函数值属性存在,当一个对象转换为初始值时调用) 如果存在, 调用返回原始值
  2. 调用 valueOf 看看返回的是否是原始值类型 是原始值就把原始值转换为需要类型
  3. 调用 toString 转换成字符串
  4. 最后调用相应的方法(Number / Boolean / ...)转为需要的类型
// 举例感受数据类型转换步骤
// 1) Symbol.toPrimitive 函数可重写
const obj = {
[Symbol.toPrimitive](hint) {
 if (hint === 'number') {
   return 10;
 }
 if(hint === 'string'){
     return 'hello'
 }
return 'Default'
},
};
console.log(Number(obj)) // 10
console.log(+obj)        // 10
console.log(String(obj)) // 'hello'


// 2) 不存在 Symbol.toPrimitive  调用 valueOf 并返回的是原始值
const obj2 = {
 valueOf(){
     console.log('你调用了valueof方法')
     return 'valueOf'
 }
}
console.log(''+ obj2)   // 'valueOf'
console.log(+obj2)      // NaN


// 3) 不存在 Symbol.toPrimitive  并且 valueOf 返回的不是原始值 调用 tostring
// 3.1
const obj3 = {
 valueOf(){
     return {}
 },
 toString(){
     return 'Hello'
 }
}
console.log(obj2 + 'world')  // Helloworld
console.log(+obj2)           // NaN

// 3.2
const obj3 = {
 valueOf(){
     return {}
 },
 toString(){
     return 10
 }
}
console.log(+obj3)      // 10
console.log('10'+obj2)  // '1010'

面试题 {} + []

{} + [] // 0

// 解析题目
// 浏览器解析到 { 会把它当作一个块的开始 解析到 } 会当作块的结束
// 虽然这个块里面没有任何代码但它也是个块
// 所以 {} + [] 等同于
    {
    
    }
    +[]
// 这样就是 + 的一元运算  +[] 等同于 Number([]) 涉及到浏览器的隐式数据类型转换
  • 按照隐式数据类型转换步骤
    1. 查看 Symbol.toPrimitive 是否存在 (不存在)
    2. 调用 valueOf() 查看是否返回的是原始值类型 (返回 [] 不是原始值类型)
    3. 调用 toString() 返回 ''
    4. 调用 Number() 转换为 0

面试题 [] + {}

[] + {} // '[object Object]'

// 解析题目
// 数组 + 对象  隐式转换为原始值类型
// 空数组调用 toString 方法返回 '' 
// 对象调用 toString 方法放回 '[object Object]'
'' + '[object Object]' // '[object Object]'

// 拓展 (数据类型检测)
{}.toString() // '[object Object]'
// 其实是调用的 Object 原型上的 toString 方法所以等同于 Object.prototype.toString.call({})
// 需要利用 call 改变this指向
  • [] 按照隐式数据类型转换步骤
    1. 查看 Symbol.toPrimitive 是否存在 (不存在)
    2. 调用 valueOf() 查看是否返回的是原始值类型 (返回 [] 不是原始值类型)
    3. 调用 toString() 返回 ''
  • {} 按照隐式数据类型转换步骤
    1. 查看 Symbol.toPrimitive 是否存在 (不存在)
    2. 调用 valueOf() 查看是否返回的是原始值类型 (返回 [] 不是原始值类型)
    3. 调用 toString() 返回 '[object Object]'
  • 由此得到
    • '' + '[object Object]'
    • (+)号此处做字符串拼接
    • 结果为 '[object Object]'

后期有时间更新parseInt() 和 Number() 的区别及原理 如有不对的地方, 还请留言, 一起共同探讨...