JS、递归、函数栈例子,难懂
JS, Recursion, Function Stack Example, Hard to Understand
下面是来自 MDN Function scope 的示例。我不明白 end: 0
和 end:
的其余部分是如何打印的。我原以为 console.log("end: " + i);
永远不会达到。
function foo(i) {
if (i < 0) return;
console.log("begin: " + i);
foo(i - 1);
console.log("end: " + i);
}
foo(3);
输出:
begin: 3
begin: 2
begin: 1
begin: 0
end: 0
end: 1
end: 2
end: 3
如果我写:
console.log("begin");
my_custom_function(1);
console.log("end")
然后 console.log
将开始记录,然后 my_custom_function
将被调用,当 my_custom_function
完成后它将从它停止的地方开始并且 console.log
将记录结束。
一模一样
当 foo
完成后,它将 return 到调用函数(恰好也是 foo
)并从中断处继续。
所有递归的诀窍是退出条件。没有它,该函数将永远 运行 或系统 运行 内存不足。 foo
的退出条件是 if (i < 0) return;
。
现在因为 javascript 至少在这种情况下是 运行 同步的,所以它会在继续下一行代码之前完成它正在做的任何事情。
该函数使用 foo(i - 1);
调用自身,后者将依次调用自身,依此类推,直到满足退出条件。因此,将退出条件置于递归调用之前至关重要。
为了更容易理解,请考虑每个连续调用的 i
的值:
foo(3)
foo(2)
foo(1)
foo(0) // exit condition is met, ending the recursion
print end 0
print end 1
print end 2
print end 3
分块考虑。下面我添加了显示实际 i
值并在每次递归时缩进的每个步骤。可以看到递归完成后,就会完成对前面每一个块的函数调用。
foo(3) {
if (3 < 0) return;
console.log("begin: " + 3);
foo(3-1) {
if (2 < 0) return;
console.log("begin: " + 2);
foo(2-1) {
if (1 < 0) return;
console.log("begin: " + 1);
foo(1-1) {
if (0 < 0) return;
console.log("begin: " + 0);
foo(0-1){
if (-1 < 0) return; // Exit recursion
}
console.log("end: " + 0);
}
console.log("end: " + 1);
}
console.log("end: " + 2);
}
console.log("end: " + 3);
}
function foo() {
if (i < 0) {
console.log("end: " + i);
clearInterval(lauch);//close the interval
} else { // with an else
console.log("begin: " + i);
i -= 1;
}
}
var i = 3;//global var
var lauch;
start();
function start () {
lauch = setInterval(foo, 1000); // 1 sec or 1000 millisecondes, the function reaload
}
也许这是您要找的?
下面是来自 MDN Function scope 的示例。我不明白 end: 0
和 end:
的其余部分是如何打印的。我原以为 console.log("end: " + i);
永远不会达到。
function foo(i) {
if (i < 0) return;
console.log("begin: " + i);
foo(i - 1);
console.log("end: " + i);
}
foo(3);
输出:
begin: 3
begin: 2
begin: 1
begin: 0
end: 0
end: 1
end: 2
end: 3
如果我写:
console.log("begin");
my_custom_function(1);
console.log("end")
然后 console.log
将开始记录,然后 my_custom_function
将被调用,当 my_custom_function
完成后它将从它停止的地方开始并且 console.log
将记录结束。
一模一样
当 foo
完成后,它将 return 到调用函数(恰好也是 foo
)并从中断处继续。
所有递归的诀窍是退出条件。没有它,该函数将永远 运行 或系统 运行 内存不足。 foo
的退出条件是 if (i < 0) return;
。
现在因为 javascript 至少在这种情况下是 运行 同步的,所以它会在继续下一行代码之前完成它正在做的任何事情。
该函数使用 foo(i - 1);
调用自身,后者将依次调用自身,依此类推,直到满足退出条件。因此,将退出条件置于递归调用之前至关重要。
为了更容易理解,请考虑每个连续调用的 i
的值:
foo(3)
foo(2)
foo(1)
foo(0) // exit condition is met, ending the recursion
print end 0
print end 1
print end 2
print end 3
分块考虑。下面我添加了显示实际 i
值并在每次递归时缩进的每个步骤。可以看到递归完成后,就会完成对前面每一个块的函数调用。
foo(3) {
if (3 < 0) return;
console.log("begin: " + 3);
foo(3-1) {
if (2 < 0) return;
console.log("begin: " + 2);
foo(2-1) {
if (1 < 0) return;
console.log("begin: " + 1);
foo(1-1) {
if (0 < 0) return;
console.log("begin: " + 0);
foo(0-1){
if (-1 < 0) return; // Exit recursion
}
console.log("end: " + 0);
}
console.log("end: " + 1);
}
console.log("end: " + 2);
}
console.log("end: " + 3);
}
function foo() {
if (i < 0) {
console.log("end: " + i);
clearInterval(lauch);//close the interval
} else { // with an else
console.log("begin: " + i);
i -= 1;
}
}
var i = 3;//global var
var lauch;
start();
function start () {
lauch = setInterval(foo, 1000); // 1 sec or 1000 millisecondes, the function reaload
}
也许这是您要找的?