如下全部結論均基於PHP5版本
看下面一段最基礎的foreach遍歷數組代碼。php
<?php $arr = array(‘a’,’b’,’c’); foreach ($arr as $key=> $value) { echo $key,$value,’<br/>’; //output : 0a1b2c } ?>
輸出爲’0a1b2c’天然沒有疑問,那麼此過程當中$arr,$key,$value到底是通過怎樣的運算,才輸出這個結果的呢?數組
其實foreach遍歷過程當中,並非直接操做$arr(原數組)的,而是會將$arr複製出一個$arrcopy(是一個$arr的一個複製品,我這裏以$arrcopy代替),foreach在遍歷過程當中操做的其實一直是$arrcopy。
注:關於$arrcopy這個值咱們是沒辦法提取出來的,由於這是我給他的命名,並無存在這個變量,可是foreach遍歷過程當中確實會產生這麼一個副本,這兒爲了方便講述我用$arrCopy表明。
Foreach遍歷大概的流程是這樣(僞代碼):函數
<?php //僞代碼 $arr = array('a','b','c'); /* foreach循環開始*/ //first loop $arrCopy = $arr; //複製出一個待循環數組的副本,接下來都是操做這個副本 $key = currentKey($arrCopy); //將獲取到的值分配給$k; $val = currentVal($arrCopy); //將獲取到的值分配給$v; next($arrCopy);//移動副本數組的指針 $arr = $arrCopy;//將副本賦值回給$arr((主要是將指針同步移動)) //大括號內容 { echo $key,$value,’<br/>’; } //firt loop end //second loop $key = currentKey($arrCopy); //將獲取到的值分配給$k; $val = currentVal($arrCopy); //將獲取到的值分配給$v; ……… //seconde loop end ?>
這就是foreach代碼的運行流程,總結一句話就是foreach遍歷操做的時候並非原始數組,而是一個拷貝數組,可是每次循環的結尾都會將副本從新賦值回給原數組$arr = $arrCopy;。oop
如何證實個人說法呢?能夠用下面這段代碼檢驗。spa
<?php // $a = array('a','b','c'); $arr = array('a','b','c'); foreach ($arr as $key=> $value) { $arr[] = 'd'; print_r($arr); var_dump($key,$value); } ?>
輸出結果爲:指針
//output: Array ( [0] => a [1] => b [2] => c [3] => d ) int(0) string(1) "a" Array ( [0] => a [1] => b [2] => c [3] => d [4] => d ) int(1) string(1) "b" Array ( [0] => a [1] => b [2] => c [3] => d [4] => d [5] => d ) int(2) string(1) "c"
同窗們看出來了嗎?
$arr數組的鍵值對一直在在增長,但是$key,$value的值到了int(2),string(1) 「c」就結束了,並無如咱們所料的將值爲d的那些鍵值對打印出來。
這兒就能證實,foreach遍歷過程操做的是$arr的副本($arrcopy)。code
對了,foreach使用過程當中還有一些小地方須要注意。
例如foreach遍歷數組的指針問題:blog
<?php $arr = array('a','b','c'); var_dump(current($arr)); //output:string(1) "a" foreach ($arr as $key=> $value) { } var_dump(current($arr)); //output:bool(false) ?>
兩次輸出,不同的結果。爲何呢?由於foreach循環遍歷後的數組,該數組的指針是指向末尾的(此處的話指針就是在’c’的右邊),而且使用完畢後不會幫咱們復位,因此咱們var_dump(current($arr))爲 bool(false)。
那麼在這裏咱們須要特別注意,爲了保險起見咱們在foreach遍歷數組後,最好手動reset()一下數組,防止出錯:圖片
<?php $arr = array('a','b','c'); var_dump(current($arr)); //output:string(1) "a" foreach ($arr as $key=> $value) { } reset($arr); var_dump(current($arr)); / output:string(1) "a" ?>
這樣就正常了。同步
還有一點PHP手冊也提醒咱們了:
轉成代碼的意思就是:
<?php $arr = array('a','b','c'); foreach ($arr as $key=> $value) { } var_dump($key); var_dump($value); ?>
Foreach遍歷後,$key和$value是真實存在的,最好使用後能手動unset()掉。
總結:foreach算是PHP裏面比較複雜的一個函數了,由於牽扯到PHP底層的C語言的結構體,引用(is_ref__gc),指針移動……,因此在使用foreach的時候必定要特別注意啊!