为什么Safari会递归调用function.apply?

per*_*iae 3 javascript safari

考虑以下:

var foo = []
for (var i=0; i<100000; i++) { foo.push(97); }
var bar = String.fromCharCode.apply(String,foo)
Run Code Online (Sandbox Code Playgroud)

大多数浏览器运行良好,但Safari抛出: RangeError: Maximum call stack size exceeded.

基于此,似乎Safari的Function.prototype.apply实现是递归的.这是真的?

上面链接的MDN页面提到了JS引擎的参数长度限制的潜在问题,但这显然不是这里的情况.

编辑:我仍然不认为这是一个论证长度问题.通过这个页面和我自己的测试,看起来Safari可以处理多达524197个参数,上面的代码不会超过这些参数.

额外的问题:我们可以重写上面的代码,以避免通过显式调用String.fromCharCode数组的每个元素join并将结果放在一起来使用apply ,但我怀疑它会更慢(对于支持大输入的浏览器apply).从整数字符代码数组中组装大字符串的最佳方法是什么?

Bub*_*les 5

Apply在某些浏览器中对它们接受的参数长度有限制.Webkit的观察限为2 ^ 16,因此如果您有任何需要,您可能需要遵循策略来打破争论.如果您阅读了该错误的详细信息,那么这是一个强制性的限制,而不是它是由递归引起的问题(该错误也引发了类似的RangeError).

无论如何,我相信你对字符串连接的预感是正确的 - 连接不一定和其他方法一样好.这是对字符串连接的测试,我首先分解参数(类似于MDN讨论中的策略),并且它会使连接边缘化.直接将字符串添加到一起甚至逐渐加入连接,我有点惊讶(至少在Chrome中,我想他们必须只有一些可以重用现有字符串才能产生效果的智能gc,但可以肯定地说).

编辑 - 有趣的是,就加入速度慢而言,Chrome看起来很奇怪 - 对于其他所有浏览器而言,它在性能方面甚至更好地接近concat.