valueOf 和 toString 几乎都是在出现操作符(+-*/==><)时被调用(隐式转换)
toString
调用
-
表示对象的时候,变成
[object Object] -
表示数组的时候,相当于
Array.join(',')
let a = {}
let b = [1, 2, 3]
let c = '123'
let d = function(){ console.log('fn') }
console.log(a.toString()) // '[object Object]'
console.log(b.toString()) // '1,2,3'
console.log(c.toString()) // '123'
console.log(d.toString()) // 'function(){ console.log('fn') }'
- 某种场合
toString比typeof&instanceof更高效准确
toString.call(()=>{}) // [object Function]
toString.call({}) // [object Object]
toString.call([]) // [object Array]
toString.call('') // [object String]
toString.call(22) // [object Number]
toString.call(undefined) // [object undefined]
toString.call(null) // [object null]
toString.call(new Date) // [object Date]
toString.call(Math) // [object Math]
toString.call(window) // [object Window]
-
隐式转换
- 操作符一边为对象,则会先调用
toSting方法
- 操作符一边为对象,则会先调用
let c = [1, 2, 3]
let d = {a:2}
Object.prototype.toString = function(){
console.log('Object')
}
Array.prototype.toString = function(){
console.log('Array')
return this.join(',') // 返回toString的默认值(下面测试)
}
console.log(2 + 1) // 3
console.log('s') // 's'
console.log('s'+2) // 's2'
console.log(c < 2) // false (一次 => 'Array')
console.log(c + c) // "1,2,31,2,3" (两次 => 'Array')
console.log(d > d) // false (两次 => 'Object')
重写toString方法
class A {
constructor(count) {
this.count = count
}
toString() {
return '我有这么多钱:' + this.count
}
}
let a = new A(100)
console.log(a) // A {count: 100}
console.log(a.toString()) // 我有这么多钱:100
console.log(a + 1) // 我有这么多钱:1001
valueOf
let c = [1, 2, 3]
let d = {a:2}
console.log(c.valueOf()) // [1, 2, 3]
console.log(d.valueOf()) // {a:2}
两者区别
共同点:在输出对象时会自动调用
不同点
-
默认返回值不同,且存在优先级关系
-
对象转换时,将优先调用
toString方法-
没有重写
toString,将调用valueOf方法 -
两个方法都没有重写,按
Object的toString输出
-
-
强转字符串类型时,将优先调用
toString方法,强转为数字时优先调用valueOf -
使用运算操作符时,
valueOf的优先级高于toString -
数值运算中,优先调用了
valueOf -
字符串运算中,优先调用了
toString
class A {
valueOf() {
return 2
}
toString() {
return '哈哈哈'
}
}
let a = new A()
console.log(String(a)) // '哈哈哈' => (toString)
console.log(Number(a)) // 2 => (valueOf)
console.log(a + '22') // '222' => (valueOf)
console.log(a == 2) // true => (valueOf)
console.log(a === 2) // false => (严格等于不会触发隐式转换)
暂且先把 valueOf 方法去掉
class A {
toString() {
return '哈哈哈'
}
}
let a = new A()
console.log(String(a)) // '哈哈哈' => (toString)
console.log(Number(a)) // NaN => (toString)
console.log(a + '22') // '哈哈哈22' => (toString)
console.log(a == 2) // false => (toString)
去掉 toString 方法看看
class A {
valueOf() {
return 2
}
}
let a = new A()
console.log(String(a)) // '[object Object]' => (toString)
console.log(Number(a)) // 2 => (valueOf)
console.log(a + '22') // '222' => (valueOf)
console.log(a == 2) // true => (valueOf)
class A {
valueOf() {
return 2
}
}
let a = new A()
Object.prototype.toString = null;
console.log(String(a)) // 2 => (valueOf)
console.log(Number(a)) // 2 => (valueOf)
console.log(a + '22') // '222' => (valueOf)
console.log(a == 2) // true => (valueOf)
[Symbol.toPrimitive]
-
当做一个函数
- 内置的 Symbol 值
-
作用:同
valueOf()和toString()一样,但是优先级要高于这两者 -
该函数被调用时,会被传递一个字符串参数
hint,表示当前运算的模式,一共有三种模式-
string:字符串类型
-
number:数字类型
-
default:默认
-
class A {
constructor(count) {
this.count = count
}
valueOf() {
return 2
}
toString() {
return '哈哈哈'
}
// 我在这里
[Symbol.toPrimitive](hint) {
if (hint == "number") {
return 10;
}
if (hint == "string") {
return "Hello Libai";
}
return true;
}
}
const a = new A(10)
console.log(`${a}`) // 'Hello Libai' => (hint == "string")
console.log(String(a)) // 'Hello Libai' => (hint == "string")
console.log(+a) // 10 => (hint == "number")
console.log(a * 20) // 200 => (hint == "number")
console.log(a / 20) // 0.5 => (hint == "number")
console.log(Number(a)) // 10 => (hint == "number")
console.log(a + '22') // 'true22' => (hint == "default")
console.log(a == 10) // false => (hint == "default")
- 特殊的是(+)拼接符,这个属于
default的模式
划重点:此方法不兼容IE