"recursion"、"a non-terminating procedure that happens to refer to itself"和"repeated scheduling"有什么区别



此问题旨在作为规范的问题/答案,用于消除描述性术语"递归"或"递归"的歧义。在适用的范围内,"碰巧提及自身的非终止程序"和"重复调度"。


JavaScript定义和区别是什么

  1. "递归";
  2. "碰巧提及自身的非终止程序";以及
  3. "重复调度">

我经常看到当函数重复调用自己时使用术语"递归",尽管JavaScript中"递归"的明确定义是什么?

我很少看到描述函数模式时使用的术语"碰巧引用自身的非终止过程"或"重复调度";经常使用"递归"或"递归"来描述在函数调用主体中对开始该过程的原始函数进行函数调用的模式。

什么时候"递归">

不适用于特定的函数模式;"递归"、"碰巧引用自身的非终止过程"和"重复调度"之间的明确定义和区别是什么?

递归

我经常看到当函数重复调用自己时使用术语"递归",尽管JavaScript中"递归"的明确定义是什么?

这个定义似乎很好,但该函数不必直接调用自己即可递归,它的执行只需要导致它再次被调用。函数不直接调用自身的递归示例是:调用A();调用B();调用C();再次调用A();

重复调度

像这样的函数使用重复调度:

function A ( foo ) {
var bar;
setTimeout( A, 0 );
console.log( 'hello' );
}

它不是递归的,因为 A 不会在同一调用堆栈上重复调用。当当前调用堆栈完成(这意味着"hello"将被记录)并且在事件循环中再次调用 A 之前没有其他内容时,将调用 A。除了同步和异步代码之间的差异之外,这里的重要区别是一次只有一个foobar的副本,并且调用堆栈没有增长,因此不会有内存或最大调用堆栈大小超出错误,这个使用递归的版本会有这种情况:

function A ( foo ) {
var bar;
A();
console.log( 'hello' );
}

在这种情况下,"hello"将永远不会打印,因为A在到达日志记录语句之前调用自己。

引用自身的非终止过程

非终止过程只是一个无限循环。引用自己有些毫无意义:

function A ( ) {
// Never terminates
while ( true ) {
// If A() is called here, or before
// the loop you have infinite 
// recursion and a stack size error
}
// If, instead, A() is called here,
// you just have an infinite-loop,
// since this statement is never reached
}

最新更新