说明
- toString()
- valueOf()
这两个方法几乎出现在js中所有类型对应的内置对象的原型上(null和undefined除外),它们的出现解决了值运算的问题,但也出现了隐式转换这个让人头疼的问题。
toString()
返回一个表示当前值的特殊字符串,当对象表示为文本或以期望字符串被调用时,toString()方法会自动调用,比如用console.log()或者alert()方法输出值时,就会自动调用该方法,在进行值比较时,也可能触发该方法,也有可能触发valueOf方法,关于何时触发这两个方法,下文会进行介绍。
<script>
<script>
var str = "1";
var num = 1;
var boolean = true;
var obj = {};
var func = function() {}
console.log(str.toString()); //1
console.log(num.toString()); //1
console.log(boolean.toString()); //true
console.log(obj.toString()); //["object Object"]
console.log(func.toString()); //function(){}
</script>
js中许多的类型对象上都重写了Object原型上的toString方法,我们还发现,当对象调用toString()时,它会返回一个表示当前值类型的字符串,它直接调用了Object原型上的toString。
比较对象
typeof 可以用来判断基本类型变量的类型(null除外,null会返回object,这是js历史遗留问题),当我们用typeof来比较对象时,发现并行不通,因为它都会返回一个object,比如当我们运用深拷贝copy对象时,就不能准确地判断出数组和对象,并做出相应的处理,因为它们都会返回一个object。
object原型上的toString方法,可以返回一个表示值类型的一个字符串,那么我们就可以使用object原型上的toString方法来判断对象。
<script>
var toString = Object.prototype.toString
toString.call(1) // '[object Number]'
toString.call('1') // '[object String]'
toString.call(false) // '[object Boolean]'
toString.call(() => {}) // '[object Function]'
toString.call([]) // '[object Array]'
toString.call({}) // '[object Object]'
toString.call(null) // '[object Null]'
toString.call(undefined) // '[object Undefined]'
toString.call(new Date()) // '[object Date]'
toString.call(window) // '[object Window]'
toString.call(Math) // '[object Math]'
</script>
运算操作时带来的隐式转换问题
var c = [1, 2, 3]
var d = {a:2}
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方法,它会把数组用join(",")方法分割,输出字符串。
toString()重写
<script>
String.prototype.toString = function() {
var num = 1;
return `myString${num}`;
}
var str = "2"
console.log(str.toString()); //myString1
</script>
valueOf()
返回当前包装对象的原始值。
这个 API 通常是由 JavaScript 引擎内部调用,开发者一般情况下不会使用,其功能和 toString 大同小异。
二者区别
共同点:两者都是在值运算的时候会自动调用,从而触发隐式转换
不同点:默认返回值不同,并且存在调用优先级关系
在二者并存的情况下,数值运算时优先使用 valueOf ,字符运算时优先使用 toString 。
class A {
construtor(num) {
this.num = num
}
valueOf() {
return this.num
}
toString() {
return `我好有钱:${this.num}`
}
}
const a = new A(100)
console.log(String(a)) // '我好有钱:100' -> toString
console.log(Number(a)) // 100 -> valueOf
console.log(a + '22') // '10022' -> valueOf
console.log(a == 100) // true -> valueOf
console.log(a === 100) // false,全等不触发隐式转换
总结
总结可以发现,valueOf 更加偏向于运算,toString 更加偏向于调用。
在进行对象运算时,将优先调用 toString 方法,如若没有重写 toString 方法,则会调用 valueOf 方法;如果两个方法都没有重写,则会调用 Object 上面的 toString
当进行强制类型转换时,如果转换成字符串则会调用 toString ,转换成数字则会调用 valueOf
使用运算符进行运算时,valueOf 的优先级高于 toString。
原文链接