为什么Safari调用函数.递归地应用
Why does Safari call function.apply recursively?
考虑以下内容:
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引擎参数长度限制的潜在问题,但这显然不是这里的情况。
EDIT:我仍然不认为这是参数长度的问题。通过这个页面和我自己的测试,看起来Safari最多可以处理524197个参数,上面的代码没有超过这个值。
附加问题:我们可以重写上面的代码,通过显式地对数组的每个元素调用String.fromCharCode
并将结果join
组合在一起来避免使用apply,但我怀疑这会更慢(对于支持大输入apply
的浏览器)。从整数字符代码数组中组装一个大字符串的最佳方法是什么?
Apply在某些浏览器中对接受的参数长度有限制。Webkit观察到的限制是2^16,所以如果你需要更多的参数,你可能想要遵循一个策略来分解参数。如果您阅读了该bug的详细信息,就会发现这是一种强制限制,而不是由递归引起的问题(该bug也抛出了类似的RangeError)。
无论如何,我相信你对字符串连接的预感是正确的-连接不一定像其他方法一样好。下面是一个针对字符串concat的测试,我首先将参数分开(类似于MDN中关于apply的讨论中的策略),它取代了join。直接将字符串添加在一起甚至取代了join,这让我有点惊讶(至少在chrome中,我认为它们必须有一些智能gc,可以重用现有的字符串以达到很好的效果,但可以肯定地说)。
编辑-有趣的是,看起来Chrome在连接速度方面是一个奇怪的人-对于其他浏览器来说,它在性能方面更接近concat甚至更好。
- 数组在递归方法中设置为null
- Kendo:我该如何在树视图中创建一个递归的hieiarchy
- 递归使用 eval() 是检查程序执行的好方法吗?
- 使用递归、Ramda.js和无点样式重构字符串的getPermutations()
- 递归深度比较
- Eloquent JavaScript递归示例如何终止为返回1,但仍然输出指数值
- 递归函数中断
- 如何递归地获取嵌套对象中所有子对象的列表
- JavaScript 素数搜索无限递归
- 在递归生成器函数中,yield后面的*(星号/星号)语法意味着什么
- 递归|两个函数名
- 有没有一种方法可以在Javascript中进行可变递归currying
- 如何对不同的表递归使用以下代码
- 将jQuery对象传递到setTimeout递归函数中
- 有更好的方法吗?(递归解析HTML unicode实体)
- 为什么递归生成器函数没有't在ES2015工作
- 通过Windows应用商店Javascript应用程序中的图片库递归
- 我如何写一个应用程序使用递归函数,可以启动/停止
- 如何在ES5中对递归匿名函数应用TCO(尾部调用优化)?
- 为什么Safari调用函数.递归地应用