js--对象 — 原始值转换

687 阅读2分钟

对象 — 原始值转换

对象在所有布尔上下文中都是 true。

只存在字符串转换和数值转换。

hint

规范明确描述了哪个运算符使用哪个 hint。

当一个对象被用在需要原始值的上下文中时,例如,在 alert 或数学运算中,对象会被转换为原始值。

对象到原始值的转换有三种变体(hint)。

"string"

对象到字符串的转换。

alert(obj)
String({})

"number"

对象到数字的转换

Number({})
let date  = date1- date2

"default"

在不确定对象转换为字符还是数值时。

let val = obj1 + obj2 //二元运算符+可以用于字符连接,也可用于数值相加

<> 这样的小于/大于比较运算符,也可以同时用于字符串和数字。不过,它们使用 “number” hint,而不是 “default”。这是历史原因。

转换

转换规则:

为了进行转换,js会调用三个对象方法。

首先 调用obj[Symbol.toPrimitive] (hint),如果该方法存在。

否则 如果hint为string ,会依次调用obj.toString(),obj.valueOf(),无论哪个存在。

否则 ,如果为hint为number或者default,依次调用obj.valueOf(),objtoString(),无论哪个存在。

obj[Symbol.toPrimitive] (hint)

hint 有三种类型,我们可以根据不同类型进行处理。

let obj = {
   name: '红雷',
   age: '23',
   [Symbol.toPrimitive]: function(val) {
       console.log('hint:', val)
     return val === 'string' ? this.name : this.age
    }
 }
 console.log(Symbol(obj)) // hint: string  Symbol(红雷)  
 console.log(obj - 1)     // hint: number   22
  console.log(obj + 1)    // hint: default  24

方法必须返回一个原始值,否则就会出现 error。

let obj = {
   name: '红雷',
   age: '23',
   [Symbol.toPrimitive]: function(val) {
       console.log('hint:', val)
       return {}
    }
 }
 console.log(Symbol(obj)) 
 // hint: string   
 // Uncaught TypeError: Cannot convert object to primitive value
 console.log(obj - 1)   
 console.log(obj + 1) 

toString/valueOf

如果没有Symbol.toPrimitive ,js会进行如下处理:调用toString或者valueOf方法。

hint为string ,首先调用toString,不存在调用valueOf方法。

let obj = {
      name: '红雷',
      age: 23,
      toString(val) {
          return this.name
      },
}
console.log(Symbol(obj)) //Symbol(红雷)
console.log(obj - 1)     // NaN
console.log(obj + 1)     // 红雷1
let obj = {
      name: '红雷',
      age: 23,
      valueOf() {
         return this.age
      }
}
console.log(Symbol(obj)) // Symbol([object Object])
console.log(obj - 1)     // 22
console.log(obj + 1)     // 24

hint为number或者default,首先调用valueOf,不存在调用toString方法。

let obj = {
      name: '红雷',
      age: 23,
      toString(val) {
          return this.name
      },
      valueOf() {
         return this.age
      }
}
console.log(Symbol(obj)) //Symbol(红雷)
console.log(obj - 1)     // 22
console.log(obj + 1)     // 24

valueOf,toString方法返回值必须为原始值。返回对象会被忽略。

默认情况下 普通对象 valueOf方法返回对象自身。 toString方法返回一个字符串"[object Object]"

let obj = {
      name: '红雷',
      age: 23,
      toString(val) {
          return this.name
      },
      valueOf() {
         return this
      }
}
console.log(Symbol(obj)) //Symbol(红雷)
console.log(obj - 1)     // NaN
console.log(obj + 1)     // 红雷1

let obj = {
      name: '红雷',
      age: 23,
      toString(val) {
          return this
      },
      valueOf() {
         return this.age
      }
}
console.log(Symbol(obj)) //Symbol(23)
console.log(obj - 1)     // 22
console.log(obj + 1)     // 24