JavaScriptの再帰処理の限界
JavaScriptの再帰処理をarguments.calleeを使って書くか、関数リテラル名指定で自分を呼び出すかでエラーになった時の挙動が違ったのでメモ。
arguments.calleeの場合
| ブラウザ | エラーになる回数 | エラーメッセージ | メモ |
|---|---|---|---|
| IE6 | 438 | スタック領域が不足しています | catchできない |
| IE7 | 1747 | stack over flow at line XX. | catchできない window.onerrorでハンドルしようとするとIEがクラッシュ |
| Firefox 3.0 | 2999 | too much recursion | catchできない |
| Safari 4 Beta | 40326 | Maximum call stack size exceeded. | catchできない |
関数リテラル名指定の場合
| ブラウザ | エラーになる回数 | エラーメッセージ | メモ |
|---|---|---|---|
| IE6 | 462 | スタック領域が不足しています | catchできる |
| IE7 | 2495 | スタック領域が不足しています | catchできる |
| Firefox 3.0 | 2999 | too much recursion | catchできる |
| Safari 4 Beta | 43686 | Maximum call stack size exceeded. | catchできる |
検証コード
<html>
<head>
<title>Limit of Recursion</title>
<script>
var setup = function(){
window.onerror = function(e, fileName, row){
alert("catch失敗\nCount:"+ count + '\nMessage' + e);
}
}
var count = 0;
var test1 = function(){
count = 0;
var counter1 = function(){
count++;
arguments.callee();
}
(function(){
try {
counter1();
} catch(e){
alert('Count:' + count + '\nMessage:' + e.message);
}
})();
}
var test2 = function(){
count = 0;
var counter2 = function(){
count++;
counter2();
}
window.counter2 = counter2;
(function(){
try {
counter2();
} catch(e){
alert('Count:' + count + '\nMessage:' + e.message);
}
})();
}
</script>
</head>
<body onload="setup()">
Testing limit of recursion.<br />
<input type="button" value="Recursion by arguments.callee" onclick="test1();" />
<br />
<br />
<input type="button" value="Recursion by function name" onclick="test2();" />
</body>
</html>
jsbinにテストページを作成しました
http://jsbin.com/ileju