JavaScript中valueOf与toString的执行优先级深度解析

作者:拾光

时间:2026-10-26

浏览:563

本文深入解析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。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章