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個の引数を処理できるようですが、上記のコードはこれを超えていません。

おまけの質問: 上記のコードを書き換えてString.fromCharCode、配列の各要素を明示的に呼び出しjoinて結果をまとめることで apply の使用を避けることができますが、( large-input をサポートするブラウザーの場合apply) 遅くなると思います。整数文字コードの配列から大きな文字列を組み立てる最良の方法は何ですか?

4

1 に答える 1

5

一部のブラウザーでは、Apply が受け入れる引数の長さに制限があります。Webkit には 2^16 の制限があるため、それ以上の制限が必要な場合は、引数を分割する戦略に従うことをお勧めします。バグの詳細を読むと、これは強制的な制限であり、再帰に起因する問題ではありません (問題のバグも同様の RangeError をスローしました)。

とにかく、文字列の連結についてのあなたの推測は正しかったと思います.joinは必ずしも他の方法ほど良いとは限りません. これは、最初に引数を分割する文字列連結に対するテストです (適用に関する MDN の議論の戦略に似ています)。文字列を一緒に直接追加すると、結合が追いつかなくなりました。これには少し驚いています(少なくともクロムでは、既存の文字列を再利用して大きな効果を得ることができるスマートgcが必要だと思いますが、確かに言うことができます)。

編集 - 興味深いことに、結合がいかに遅いかという点で、Chrome は奇妙なもののようです。他のすべてのブラウザーでは、パフォーマンスの点で concat にはるかに近いか、さらに優れていました。

于 2013-01-14T22:24:11.683 に答える