函数逐步减少静态变量,但它不应该。 PHP

Function decreases static variable step by step, but it should not. PHP

有一个函数:

<?php 

 function test(){

     static $count = 0; 
     $count++;  
     echo $count;

     if ($count < 10) {
          test();
     }       

     $count--;  
     echo $count;
}

test();  

?>

这段代码产生:123456789109876543210

当 $count 递增到 10 时 - 这是可以理解的,它会一直工作直到 if 语句的计算结果为 false。 但为什么它逐渐减少到 0? 在我的新手逻辑中,此代码中的 $count-- 应该只减少到 9 一次并且函数应该停止。 没有循环或循环可以逐步降低其价值。但是我们看到,它在这里并且正在工作。 为什么会这样?

好的,所以我试着形象化这里发生的事情,这样你可能会更好地理解正在发生的事情。

事情是这样的(摘要):

//Iteration 1
function(){
    //Code before runs

    if stmt (TRUE)   //Iteration 2   
        function(); → function(){
               ←┐         //Code before runs
    //Code after│
}               │         if stmt (TRUE)          //Iteration 10  
                │             function(); → ... → function(){
                │                        ←┐           //Code before runs
                │         //Code after    │
                │     }                   │           if stmt (FALSE)
                └──── ← function returns  │
                        value and goes    │           //Code after runs
                        back to next line │       }
                                          └────── ← function returns value and goes back to next line


  • 所以在第 10 个函数调用中,if 语句为 FALSE,不再调用函数。

  • 现在第 10 次调用函数运行到最后并减少变量。

  • 它 return 是 return 值(NULL)并返回到执行函数调用的其余部分的前一个函数调用,这也减少了变量和等等...

当您更改输出以强调条件递归调用的工作原理时,事情可能会变得更清楚:

<?php
function test($level=0) {
    static $count = 0;
    $count++;
    echo str_pad('a:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;

    if ($count < 10) {
        test($level+1);
    }

    $count--;
    echo str_pad('b:', $level+2, ' ', STR_PAD_LEFT), $count, PHP_EOL;
}

test();

打印

a:1
 a:2
  a:3
   a:4
    a:5
     a:6
      a:7
       a:8
        a:9
         a:10
         b:9
        b:8
       b:7
      b:6
     b:5
    b:4
   b:3
  b:2
 b:1
b:0

您的问题似乎是理解函数调用和函数的后续 return(s) 是如何工作的。让我们从简单开始

<?php
function c() {
    echo 'c in', PHP_EOL;
    echo 'c out', PHP_EOL;
}

function b() {
    echo 'b in', PHP_EOL;
    c();
    echo 'b out', PHP_EOL;
}

function a() {
    echo 'a in', PHP_EOL;
    b();
    echo 'a out', PHP_EOL;
}

a();

打印

a in
b in
c in
c out
b out
a out

很简单,不是吗?当函数 exits/returns 时,执行从调用的地方继续。这并不绑定到函数的名称,而是函数调用自身,参见例如https://en.wikipedia.org/wiki/Call_stack.
所以即使一个函数像

这样调用自己
<?php
function foo($param) {
    echo "foo($param) in", PHP_EOL;
    if ( $param!==1 ) {
        foo(1);
    }
    echo "foo($param) out", PHP_EOL;
}

foo(0);

这不会导致单个 exit/return 取消 "same" 函数的所有函数调用,但它只会在调用堆栈中冒出一个 "scope"/帧。因此输出是

foo(0) in
foo(1) in
foo(1) out
foo(0) out

现在将其与上面的 "improved" 脚本的输出进行比较:我希望这对您有所帮助。