String(number) 是否在内部调用 number.toString?

Does String(number) call number.toString internally?

我刚刚尝试了一些东西并发现了这个:

如果您在自定义 toString 中调用 String(n),它会调用自身并抛出错误 Maximum Call Stack exceeded

JSFiddle

Number.prototype.toString = function() {
  return String(this)
}

var a = 10;
try {
  a.toString()
} catch (err) {
  console.log(err.message)
}

但是如果直接调用var b = String(a),它不会调用toString函数。

JSFiddle

Number.prototype.toString = function(){
  console.log(this);
  return '' + this;
}

var a = 10;
a.toString();

注意: 我知道上面的代码片段也抛出同样的错误,但我检查了 Nodechrome - JSFiddleFirefox - JSFiddle 和它是一致的。 var b = String(a) 不会调用 number.toString()'' + this 也会调用。这是在 ''+this.

上调用 number.toString() 的 Stack 片段中的一些优化

所以我的问题是,我错过了什么?为什么会出现这种奇怪的行为?

实际数字调用内部方法将它们转换为字符串,并且它们的输出不受 valueOftoString 的影响,除非它们被显式调用。

那么为什么首先调用 toString

这是因为在"sloppy"(非严格)模式下,this的值在传递给String(this)'' + this.

(因此,在使用严格模式的普通应用程序中,您可能看不出这两种方式之间的区别。)

由于 this 是一个对象,因此 String()+ 加法运算符都会尝试将对象转换为字符串。这通常通过调用 obj.toStringobj.valueOf.

来完成

至于为什么String(this)失败而'' + this不失败,String函数在调用valueOf.[=30之前在对象上调用了toString =]

但是,当您使用加法 (+) 运算符时,valueOftoString 的顺序会颠倒。

也许你应该使用 call/apply。

Number.prototype.toString = function() {
  console.log(this)
  return String(this)
}

var a = 10;
try {
  a.toString.call()
  console.log(a)
} catch (err) {
  console.log(err.message)
}

我认为的原因是The reason to use JS .call() method?