JavaScriptで数百MBのデータをシャベルで処理する必要があるWebページを作成しようとしています。さまざまなブラウザで、さまざまなデータ量で「最大呼び出しスタックサイズを超えました」というエラーが発生します。
コードを調べて、関数内のローカル変数をよりグローバルなスコープに移動し、スタックではなくヒープに割り当てられるようにすることで、この問題を修正できますか?または、これらの概念はJavaScriptに存在しませんか? (私が知る限り、データに主要な再帰ループがないため、エラーの原因となっているのは実際にはいくつかの巨大な文字列/数値配列です)
これが不可能な場合、ブラウザにメモリを予約するように依頼する方法はありますか?
Javascriptでは、メモリをスタック/ヒープに分離することはありません。表示されるのは、次のいずれかです。
OK、問題を理解しました。私のコードには実際には再帰はありませんでした。たとえば、私の犯罪者である <array>.splice(...)
のような「可変引数」関数である場合、数百の引数を使用してJavaScript関数を呼び出すことは確かに可能です。
余談: [〜#〜] gwt [〜#〜] Java関数 System.arraycopy(...)
を実装します JavaScriptスプライス関数を多かれ少なかれ巧妙な方法で使用します。
spliceは、ターゲット配列に挿入する任意の数の入力要素を受け入れます。次の構成を使用して、これらの入力要素を別の配列から渡すことができます。
var arguments = [index, howmany].concat(elements);
Arrays.prototype.splice.apply(targetarray, arguments);
これは、次を呼び出すことと同じです。
targetarray.splice(index, howmany, elements[0], elements[1], elements[2], ...);
elementsが大きくなった場合(さまざまなブラウザでの「big」の意味については以下を参照)、canその内容が関数呼び出しのためにスタックにロードされるため、「最大呼び出しスタックサイズを超えました」エラーなしの再帰が発生します。
この問題を示す短いスクリプトを次に示します。
var elements = new Array();
for (i=0; i<126000; i++) elements[i] = 1;
try {
var arguments = [0, 0].concat(elements);
Array.prototype.splice.apply(elements, arguments);
alert("OK");
} catch (err) {
alert(err.message);
}
このスクリプトを使用すると、「大きい」とは次のことを意味します。
そして勝者は次のとおりです。変更のためのInternetExplorer 8!この関数呼び出しが失敗する前に、すべてのシステムメモリを使い果たす可能性があります。
補足:FirefoxとOperaは実際には別の(より便利な)エラーメッセージをスローします:Function.prototype.apply:argArrayが大きすぎます