php的foreach工作原理

身居漏室,心系天下


事先声明,我们讨论的不是foreach用来做什么,和如何使用它。我们要分析的是它的工作原理。而不是说怎样用他来循环数组。

 

很长一段时间我认为foreach循环的是数组本身。但是,许多人提到,它其实是把数组做为一个副本来操作,我也认为这是最终的结论.不过,我又对这个问题进行了重新的思考,并通过实际的测试发现,

事实上也不完全如此。
让我解释一下,从下面的例子中,我们将用一个数组看出它是如何工作的。

$array = array(1, 2, 3, 4, 5); //测试用的数组.

//case 1
foreach ($array as $item) {
  echo "$item\n";
  $array[] = $item;
}
print_r($array);

/* Output in loop:    1 2 3 4 5
   $array after loop: 1 2 3 4 5 1 2 3 4 5 */


这清楚地表明,我们不用源数组直接工作 - 否则循环将永远持续下去,因为我们是在循环过程中不断加入新的元素到数组上。再用一个例子说明:

//case 2
foreach ($array as $key => $item) {
  $array[$key + 1] = $item + 2;
  echo "$item\n";
}

print_r($array);

/* Output in loop:    1 2 3 4 5
   $array after loop: 1 3 4 5 6 7 */

这将进一步验证我们的结论,我们正与在循环过程中的源数组的副本打交道,否则我们将在循环过程中看到修改后的值。但...

如果我们看一下php手册,我们会发现这条语句:

当foreach开始执行时,数组内部的指针会自动复位到数组的第一个元素。

对...这似乎表明,foreach还依赖源数组的指针。但是,我们刚刚证明了我们操作的不是源数组,对不对?事实上是这样,但也不完全是。
看下面的例子:

//case 3
// Move the array pointer on one to make sure it doesn't affect the loop
var_dump(each($array));

foreach ($array as $item) {
  echo "$item\n";
}

var_dump(each($array));

/* Output
  array(4) {
    [1]=>
    int(1)
    ["value"]=>
    int(1)
    [0]=>
    int(0)
    ["key"]=>
    int(0)
  }
  1
  2
  3
  4
  5
  bool(false)
*/

PHP手册中还指出:

作为依赖的foreach数组内部的指针在循环中改变它可能会导致意外的行为。

好吧,那什么又是“意外行为”呢?(从技术上说,任何行为是意想不到的,因为我已经不知道该期待什么)。

京ICP备14008139号-1