关于toString与valueOf执行顺序的困惑及对象字符串转换异常问题
为什么对象字符串拼接时只调用了valueOf而非toString?
我们先拆解你遇到的场景:当执行"before "+f+" after"这种字符串拼接操作时,JS会对对象f执行ToPrimitive抽象操作——这个操作的核心是把对象转换为原始值,执行顺序取决于传入的hint参数(即转换的预期类型)。
对于加法操作来说,hint的值是"default"(因为加法既可能做数值运算也可能做字符串拼接,JS无法确定预期类型),此时ToPrimitive的执行规则是:
- 优先调用对象的
valueOf()方法,若返回的是原始值(数字、字符串、布尔值等非对象类型),则直接使用这个值,流程终止。 - 只有当
valueOf()返回的不是原始值时,才会继续调用toString()方法,再检查其返回值是否为原始值。
回到你的代码:
fn.prototype.valueOf = function(){ console.log("valueOf call"); return 100; // 返回的是原始值数字100 }
因为valueOf()直接返回了原始值100,ToPrimitive操作在这里就拿到了可用的原始值,根本不会再去调用toString(),所以你看不到toString call的输出,最终用100参与字符串拼接,得到before 100 after。
如果想让toString()先被触发,有两种方式:
- 让ToPrimitive的
hint变为"string",比如使用模板字符串${f}:
此时ToPrimitive会优先调用console.log(`before ${f} after`);toString(),但因为你的toString()返回的是对象{}(非原始值),所以会接着调用valueOf(),最终输出顺序就是你预期的toString call→valueOf call→before 100 after。 - 修改
valueOf()让它返回非原始值,比如返回一个对象:
这时fn.prototype.valueOf = function(){ console.log("valueOf call"); return {}; }valueOf()返回非原始值,ToPrimitive会继续调用toString(),如果toString()返回原始值就用它,否则报错。
内容的提问来源于stack exchange,提问作者zhang xue
相关产品推荐
相关产品推荐

