简体   繁体   English

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

[英]Why does Safari call function.apply recursively?

Consider the following: 考虑以下:

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

Most browsers run it fine, but Safari throws: RangeError: Maximum call stack size exceeded. 大多数浏览器运行良好,但Safari抛出: RangeError: Maximum call stack size exceeded.

Based on this, it appears that Safari's implementation of Function.prototype.apply is recursive. 基于此,似乎Safari的Function.prototype.apply实现是递归的。 Is this true? 这是真的?

The MDN page linked above mentions potential issues with the JS engine's argument length limit, but that's clearly not the case here. 上面链接的MDN页面提到了JS引擎的参数长度限制的潜在问题,但这显然不是这里的情况。

EDIT : I still don't think it's an argument length issue. 编辑 :我仍然不认为这是一个论证长度问题。 Via this page and my own testing, it looks like Safari can handle up to 524197 arguments, which the above code does not exceed. 通过这个页面和我自己的测试,看起来Safari可以处理多达524197个参数,上面的代码不会超过这些参数。

Bonus question : We can rewrite the above code to avoid using apply by explicitly calling String.fromCharCode on each element of the array and join ing the results together, but I suspect that would be slower (for the browsers that support the large-input apply ). 奖金的问题 :我们可以重写上面的代码以避免使用通过显式调用申请String.fromCharCode阵列中的每个元素和join的结果荷兰国际集团一起,但我怀疑这将是慢(用于支持大输入浏览器apply )。 What's the best way to assemble a large string from an array of integer character codes? 从整数字符代码数组中组装大字符串的最佳方法是什么?

Apply has limits in some browsers in the length of arguments they accept. Apply在某些浏览器中对它们接受的参数长度有限制。 Webkit has an observed limit of 2^16 , so if you have any need to have more you may want to follow a strategy to break up the arguments. Webkit的观察限制为2 ^ 16 ,因此如果您有任何需要,您可能需要遵循策略来打破争论。 If you read the details of the bug, it's an enforced limitation opposed to it being a problem arising from recursion (the bug in question also threw a similar RangeError). 如果您阅读了该错误的详细信息,那么这是一个强制性的限制,而不是它是由递归引起的问题(该错误也引发了类似的RangeError)。

Anyway, I believe your hunch about string concatenation was correct - join isn't necessarily as good as other methods. 无论如何,我相信你对字符串连接的预感是正确的 - 连接不一定和其他方法一样好。 Here's a test against string concat where I first break up the arguments (similar to the strategy in the MDN discussion of apply), and it edges out join. 这里是对字符串连接的测试 ,我首先分解参数(类似于MDN讨论中的策略),并且它会使连接边缘化。 Directly adding string together even edged out join, which I'm a little surprised by (in chrome, at least, I'd imagine they must just have some smart gc that can reuse the existing string to great effect, but can say for sure). 直接将字符串添加到一起甚至逐渐加入连接,我有点惊讶(至少在Chrome中,我想他们必须只有一些可以重用现有字符串才能产生效果的智能gc,但可以肯定地说)。

Edit - interestingly, it looks like Chrome is the odd one out in terms of how slow join is - for every other browser, it was much closer to concat in terms of performance or even better. 编辑 - 有趣的是,就加入速度慢而言,Chrome看起来很奇怪 - 对于其他所有浏览器而言,它在性能方面更接近concat甚至更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能调用function.apply? - Why can I not call a function.apply? 为什么不通过function.apply()递归传递函数参数? - Why are function arguments not getting passed recursively via function.apply()? 为什么javascript在传递给function.apply()或function.call()时会改变原始类型? - Why does javascript change primitive types when passed into function.apply() or function.call()? 为什么调用 Function.apply.bind(fn, null) 调用的是 `fn.apply`,而不是 `Function.apply`? - Why call to Function.apply.bind(fn, null) calls `fn.apply`, and not `Function.apply`? Ajax调用和function.apply无限循环 - Ajax call and function.apply infinite loop 从返回的函数中调用function.apply不会传递参数 - Call function.apply from within a returned function does not pass arguments 为什么在使用function.apply时Closure不进行类型检查? - Why does not Closure type-check the parameters when using function.apply? 如果我使用function.apply(undefined,args),为什么将this设置为window? - Why is `this` set to `window` if I use `function.apply(undefined, args)`? 为什么console.log()polyfill不使用Function.apply()? - Why do console.log() polyfills not use Function.apply()? 是否可以在不更改上下文的情况下调用function.apply? - Is it possible to call function.apply without changing the context?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM