javascript隐式类型转换通过valueof()和tostring()实现:数值上下文优先调用valueof(),字符串上下文优先调用tostring();date例外,字符串转换时先调tostring()。

基本数据类型和引用类型之间的转换,核心在于 JavaScript 的 隐式类型转换机制,而 valueOf() 和 toString() 就是这个机制中两个关键的“入口方法”。它们不是用来手动转类型的工具函数,而是 JS 在需要把对象变成原始值(比如做加法、拼接字符串、比较相等)时,自动调用的钩子。
valueOf 优先用于数值上下文
当 JS 需要把一个对象转成数字(比如参与 + 运算但左边是数字、== 比较、Math.max 等),它会优先尝试调用 valueOf():
- 如果
valueOf()返回的是原始值(如 number、string、boolean),就直接用这个值继续运算; - 如果返回的仍是对象(比如没重写或返回了数组),JS 就放弃它,转而尝试
toString(); - 如果
toString()也返回对象,就会报错TypeError: Cannot convert object to primitive value。
例如:new Date() + 0 得到毫秒数,是因为 Date.prototype.valueOf() 返回的是时间戳数字;而 [1,2] + "" 得到 "1,2",是因为数组的 valueOf() 默认返回自身(对象),于是退而求其次调用 toString(),它返回逗号分隔的字符串。
toString 优先用于字符串上下文
当 JS 需要把对象转成字符串(比如 "" + obj、alert(obj)、console.log(obj) 中的隐式转换),它会先找 toString():
- 如果
toString()返回原始值,就直接转成字符串使用; - 如果返回对象,再试
valueOf(); - 两者都失败,同样报类型错误。
注意:浏览器控制台显示对象时(比如直接输入 {} 回车),显示的是 toString() 的结果("[object Object]"),不是 valueOf() 的结果(那个是对象本身)。所以日常调试看到的“字符串表现”,基本都来自 toString()。
Date 是个例外:toString 优先于 valueOf
绝大多数对象(Array、Object、Function 等)遵循“先 valueOf,后 toString”的规则,但 Date 对象相反——在字符串转换场景下,它会先调用 toString()(返回可读日期字符串),只有在数值转换时才用 valueOf()(返回毫秒数)。
这意味着:new Date() + "" → "Mon Jun 14 2026 10:06:00 GMT+0800 (CST)"(toString 起效);+new Date() → 1786702020000(valueOf 起效)。
重写这两个方法能控制转换行为
你可以通过自定义 valueOf 或 toString 来决定对象在不同场景下“看起来像什么”:
- 只重写
toString():影响字符串拼接、alert、console.log等; - 只重写
valueOf():影响数学运算、==比较(非严格)、Number()转换等; - 两个都重写:JS 仍按上下文优先调用对应方法,互不干扰。
典型应用如函数柯里化中的链式调用:add(1)(2) 能返回数字,就是靠重写了返回函数的 valueOf(和/或 toString),让 JS 在需要原始值时自动提取计算结果。











