JavaScript中valueOf与toString的执行优先级深度解析
本文深入解析JavaScript中valueOf与toString方法的执行机制。通过对比Boolean对象及自定义对象在不同运算场景下的表现,揭示了数值转换优先调用valueOf、字符串转换优先调用toString的规律,并探讨了ECMAScript规范中getValue操作对优先级反转的影响,帮助开发者准确理解类型转换底层逻辑。
valueOf与toString基础概念
在JavaScript中,valueOf()方法用于返回指定对象的原始值。其基本调用格式为:
object.valueOf(),其中object为必选参数,代表任意固有的JScript对象。
各个JavaScript固有对象的valueOf()方法定义各不相同。
| 对象 | 返回值 |
| Array | 数组的元素被转换为字符串,这些字符串由逗号分隔,连接在一起。其操作与 Array.toString 和 Array.join 方法相同。 |
| Boolean | Boolean 值。 |
| Date | 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。 |
| Function | 函数本身。 |
| Number | 数字值。 |
| Object | 对象本身。这是默认情况。 |
| String | 字符串值。 |
需要注意的是,Math和Error对象并不具备valueOf()方法。
除null外,几乎所有JavaScript数据类型都拥有valueOf()和toString()这两个方法。它们共同解决了JavaScript中值的运算与显示问题。
JavaScript的valueOf()方法总结。
valueOf()方法可以返回Boolean对象的原始值。
调用格式为booleanObject.valueOf(),返回值为booleanObject的原始布尔值。若调用该方法的对象并非Boolean类型,则会抛出TypeError异常。
具体代码示例如下:
<script type="text/javascript">
var boo = new Boolean(false);
document.write(boo.valueOf());
</script> 上述脚本执行后将输出false。
toString方法详解
接下来介绍JavaScript的toString()方法。
toString()方法可将一个逻辑值转换为字符串,并返回转换后的结果。
调用格式为booleanObject.toString(),返回值根据原始布尔值或booleanObject对象的值返回字符串"true"或"false"。若调用该方法的对象不是Boolean类型,同样会抛出TypeError异常。
当Boolean对象被用于字符串环境时,此方法会被自动调用。
以下脚本演示创建一个Boolean对象并将其转换为字符串的过程:
代码如下:
<script type="text/javascript">
var boo = new Boolean(true);
document.write(boo.toString());
</script> 脚本执行后的输出结果为:true。
先看一个例子:
自定义对象中的优先级实验
再看一个自定义对象的示例:
var aaa = {
i: 10,
valueOf: function() { return this.i+30; },
toString: function() { return this.valueOf()+10; }
}
alert(aaa > 20); // true
alert(+aaa); // 40
alert(aaa); // 50 出现上述结果的原因在于,JavaScript在内部偷偷调用了valueOf或toString方法。那么如何区分具体调用了哪个方法呢?我们可以通过另一个测试来验证。由于涉及console.log,建议在安装了Firebug的Firefox浏览器中进行实验!
测试代码如下:
var bbb = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
},
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bbb);// 10 toString
alert(+bbb); // 10 valueOf
alert(''+bbb); // 10 valueOf
alert(String(bbb)); // 10 toString
alert(Number(bbb)); // 10 valueOf
alert(bbb == '10'); // true valueOf
alert(bbb === '10'); // false 从结果来看,大致给人的印象是:转换为字符串时调用toString方法,转换为数值时调用valueOf方法。但其中有两个特例显得不协调:一是alert(''+bbb),字符串拼接理应调用toString方法;二是===操作符不进行隐式转换,因此不调用这两个方法。为了探究真相,我们需要进行更严谨的实验。
实验代码如下:
var aa = {
i: 10,
toString: function() {
console.log('toString');
return this.i;
}
}
alert(aa);// 10 toString
alert(+aa); // 10 toString
alert(''+aa); // 10 toString
alert(String(aa)); // 10 toString
alert(Number(aa)); // 10 toString
alert(aa == '10'); // true toString
接着观察valueOf的情况。
var bb = {
i: 10,
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(bb);// [object Object]
alert(+bb); // 10 valueOf
alert(''+bb); // 10 valueOf
alert(String(bb)); // [object Object]
alert(Number(bb)); // 10 valueOf
alert(bb == '10'); // true valueOf
可以发现存在差异。它不像前面toString那样统一规整。对于出现的[object Object],推测是从Object继承而来的,我们尝试移除它看看效果。
Object.prototype.toString = null;
var cc = {
i: 10,
valueOf: function() {
console.log('valueOf');
return this.i;
}
}
alert(cc);// 10 valueOf
alert(+cc); // 10 valueOf
alert(''+cc); // 10 valueOf
alert(String(cc)); // 10 valueOf
alert(Number(cc)); // 10 valueOf
alert(cc == '10'); // true valueOf 若仅重写 toString,对象转换时将忽略 valueOf。若仅重写 valueOf,字符串转换时会优先调用它。在无法调用 toString 时,只能由 valueOf 处理。针对字符串拼接的怪异现象,查阅 ECMA262-5 发现均涉及 getValue 操作。由此可知,重写会提升调用优先级,而在存在操作符时,valueOf 的优先级本就高于 toString。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
