这个-11是从哪里来的?

4
我正在尝试以下代码:

我正在玩弄以下代码:

function recaller(){
    while(x-- > 0)recaller();
}

var x = 10;
recaller();
alert(x); //-11?

但是我惊讶地发现,x 现在的值是 -11
后来我在 while 上面添加了 alert(x);,以查看它是否正确地显示了数字 100,它确实如此。
有人能解释一下 -11 是从哪里来的吗?我的调试技巧这次失败了,我不知道如何继续测试。

你在哪里看到了给你 -11alert - gdoron
1
你可以更好地使用 console.log 而不是 alert - Wouter J
@gdoron 更新了问题,在 var x = 10; recaller(); 之后。 - ajax333221
3个回答

17
您正在递归调用recaller函数,因此在递归结束时x会被多次递减——每次递归时,当您退出该递归调用时,while循环条件将被再次检查,并且该表达式会递减x。请考虑从x = 2开始会发生什么:
  1. x等于2,我们调用recaller(第一次),进入其while循环,检查x是否大于零,然后递减……
  2. x等于1,我们调用recaller(第二次),进入其while循环,检查x是否大于零,然后递减……
  3. x等于0,我们调用recaller(第三次),进入其while循环,检查x是否大于零(不是),然后递减(-1)并返回
  4. 将堆栈解开到第二次;在它的while循环中,检查x是否大于零(否),然后递减(-2)并返回
  5. 将堆栈解开到第一次;在它的while循环中,检查x是否大于零(否),然后递减(-3)并返回
  6. 返回顶层流程
  7. x=-3

那不是这样的。if 是你在我的 fiddle 中得到正确输出的原因。看一下这个 fiddle。现在你会得到 -9 - gdoron

2
当您执行以下操作时:
var x = 10;
alert(x--); // Displays 10
alert(x); // Displays 9

x--是一个后缀递减运算符,也就是在主要求值之后执行。因此:

if(x-- > 10) { 
  // Executes when x is > 10 before decrementing
}

您正在进行递归循环。也就是说,您正在执行以下操作:
function recaller(){
    while(x-- > 0)recaller();
}

哪个:

  • 将x与10进行比较
  • 递归调用
  • 将x减一

由于您的条件是x > 0,因此当x = 0时,它将从最内部对recaller的调用中退出一次,然后进行一次递减,退出到下一个递归调用,以此类推,直到达到-11。


2

正如你可能已经知道的那样,x--会将x减一并返回减一前的值。我们也可以这样编写你的代码:

function recaller() {
    while(true) {
        var oldX = x;
        x--;
        if(!(oldX < 0)) {
            break;
        }
        recaller();
    }
}

现在将日志记录放入其中变得更容易了。我认为通过一些缩进可以更容易地看到它,所以我有一些此处未显示的函数。通过一些日志记录,它看起来像这样:

function recaller() {
    indent();
    log("Recaller called");
    while(true) {
        log("In loop, before decrement and test");
        var oldX = x;
        x--;
        log("In loop; decremented");
        if(!(oldX > 0)) {
            log("Test failed");
            break;
        }
        log("Test succeeded");
        log("In loop, before recursion");                    
        recaller();
        log("In loop, after recursion");
    }
    log("About to return from recaller");
    dedent();
}

您可以在JSFiddle上查看结果
从日志中可以看出,即使测试失败,它也会将其递减(到零以下),导致负数。

+1 我希望我能像那样调试,这将节省我很多时间。 - ajax333221

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接