对象 — 原始值转换
对象在所有布尔上下文中都是 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