私は再帰関数を要するという問題に取り組んでいると、ネストされた実行は、親のパラメータを変更しているように見えることに気づいた:再帰関数には特別な有効範囲規則がありますか?
var foo = function(ar) {
console.log('Calling function - Array: ' + ar.toString());
if(ar.length > 1){
var ele = ar.pop();
foo(ar);
console.log('Function recursion ends - Array: ' + ar.toString() + ' Popped: ' + ele);
return;
} else {
console.log('Function ends - Array: ' + ar.toString());
return;
}
}
foo([1,2,3]);
出力(インデント鉱山):
/* Calling function - Array: 1,2,3 Calling function - Array: 1,2 Calling function - Array: 1 Function ends - Array: 1 Function recursion ends - Array: 1 Popped: 2 Function recursion ends - Array: 1 Popped: 3 <-- What happened to 2? */
私は[1,2,3]
で関数を呼び出しているので、これは奇妙に思えます。そして、関数の最初の反復では、両方の要素の間に渡された要素のすべてを維持することが期待されます。ar
とele
- その代わりに、関数が終了すると、指定された配列には1
しか残りません。2
はどうなりましたか?ネストされた実行pop
は最初の実行の変数から外しましたか?
JavaScriptで関数スコープの私の理解では、関数に渡された変数はローカルでのみそれらを変更することができ、ここで見られるように、グローバル/親の範囲に戻ってそれらをエクスポートしていないと言うでしょう:
var bar = 'bar';
function doBar(bar){
bar = 'foo';
}
doBar(bar);
console.log(bar); //Outputs 'bar';
しかし、出力再帰関数からその理解に挑戦するようだ。
これらのネストされた実行が親のパラメータを変更して、不足している2
を戻さないようにするにはどうすればよいですか? JavaScriptのスコープの理解が間違っていますか?
この質問を開く前にストローで把握する私の哀れな試みで、私はクロージャ内の関数を実行しようとしました:
var foo = function(ar) {
console.log('Calling function - Array: ' + ar.toString());
if(ar.length > 1){
var ele = ar.pop();
(function(foo, ar){
foo(ar);
})(foo, ar)
console.log('Function recursion ends - Array: ' + ar.toString() + ' Popped: ' + ele);
return;
} else {
console.log('Function ends - Array: ' + ar.toString());
return;
}
}
しかし、私は閉鎖を使用せずに同じ結果を得ました - 私は明らかにar
とfoo
で渡されたので、それは閉鎖なしと変わらないものであると思う。
入れ子になったのfoo()あなたが何かをログに記録する前に、アレイ上で実行されます。入れ子にされた 'foo()'の前にロギングを試みてください。 – charlietfl
いいえ、再帰について特別なことは何もなく、これはスコープとは関係ありません。すべての呼び出しは独自の 'ar'変数を作成します。彼らはすべて同じ配列オブジェクトを参照し、 'pop'はそれを突然変異させるだけです。 – Bergi
彼らはあなたが「Function recursion ends ...」のロギングを始める時に、コンソールがあなたに何を伝えているかを与えられていますか? – JonSG