3

考虑以下:

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

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

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

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

编辑:我仍然认为这不是参数长度问题。通过这个页面和我自己的测试,看起来 Safari 最多可以处理 524197 个参数,上面的代码没有超过。

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

4

1 回答 1

5

Apply 在某些浏览器中对它们接受的参数长度有限制。Webkit 观察到的限制为 2^16,因此如果您需要更多,您可能需要遵循一种策略来分解参数。如果您阅读错误的详细信息,这是一个强制限制,而不是递归引起的问题(有问题的错误也引发了类似的 RangeError)。

无论如何,我相信您对字符串连接的预感是正确的 - join 不一定和其他方法一样好。这是一个针对字符串 concat 的测试,我首先分解了参数(类似于 MDN 讨论中应用的策略),它超越了连接。直接将字符串添加在一起甚至超出了连接,这让我有点惊讶(至少在 chrome 中,我想他们必须有一些智能 gc 可以重用现有字符串以达到很好的效果,但可以肯定地说)。

编辑 - 有趣的是,就连接速度而言,Chrome 似乎是一个奇怪的问题 - 对于其他所有浏览器,它在性能方面更接近 concat 甚至更好。

于 2013-01-14T22:24:11.683 回答