foreach處理對象數組和處理一般數組的區別

foreach處理對象數組:是處理對象的引用,所以經過foreach處理後,對象數組中的對象的數據發生了改變。

foreach處理普通數組:把原數組拷貝一個後,再從中拿出每個元素,我們使用foreach對這些元素進行處理,並不是對原數組的處理,而只是對一個拷貝的處理,所以不管我們怎麼改變其值,原數組的值是不會改變的。

例子如下:

/**     
 * 先編寫一個簡單的類,存儲HTML控件數據的類     
 */      
class Element {       
    /**     
     * 這裏只作演示,一切簡單化處理     
     */      
    protected $name;       
    protected $value;       
      
    public function __construct($name,$value){       
        $this->name = $name;       
        $this->value = $value;       
    }       
           
    public function setName($name){       
        $this->name = $name;       
    }       
}       
      
   $element_list = array();       
   for($i=0;$i<2;$i++){//生成一個擁有2個Element對象的數組       
      $element_list[] = new Element('name_'.$i,'value_'.$i);        
   }       
          
   //先打印出$element_list,查看$element_list當前數據       
   echo '--------old $element_list start--------';       
   print_r($element_list);       
   echo '--------old $element_list end--------';       
          
   /**     
    * 使用foreach對$element_list的元素進行處理     
    * 處理過後,$element_list的元素應該和原來一樣,是不變的     
    * 因爲foreach不會對原數組的值產生影響     
    */      
   foreach($element_list as $key=>$element){       
      $element->setName('changed');       
   }       
          
   //我們再打印$element_list來看看它當前的值       
   echo '--------new $element_list start--------';       
   print_r($element_list);       
   echo '--------new $element_list end--------';       
/*以下是輸出結果        
--------old $element_list start--------     
Array     
(     
    [0] => Element Object     
        (     
            [name:protected] => name_0     
            [value:protected] => value_0     
        )     
    
    [1] => Element Object     
        (     
            [name:protected] => name_1     
            [value:protected] => value_1     
        )     
    
)     
--------old $element_list end---------     
    
-------new $element_list start--------     
Array     
(     
    [0] => Element Object     
        (     
            [name:protected] => changed     
            [value:protected] => value_0     
        )     
    
    [1] => Element Object     
        (     
            [name:protected] => changed     
            [value:protected] => value_1     
        )     
    
)     
--------new $element_list end--------     
*/   

從輸出結果可以看出$element_list中對象的數據已經改變,這和原先 我們所瞭解的使用foreach遍歷數組元素,對元素進行處理不會影響到原數組的值是相沖突的,是不是PHP有BUG呢?並不是,出現這種情況的原因 是,PHP5對所有對象都是使用引用,這與PHP4是完全不同的,PHP4在新建對象是要使用&操作符來說明等到的是對象的引用。

  既然是引用,那麼$element_list數組裏面存儲的也都只是 Element對象的引用而不是一個對象拷貝。然後我們回到foreach中來,foreach處理數組時,是把原數組拷貝一個後,再從中拿出每個元素, 我們使用foreach對這些元素進行處理,並不是對原數組的處理,而只是對一個拷貝的處理,所以不管我們怎麼改變其值,原數組的值是不會改變的(這個只 對普通的變量有用,PHP5中的對象就不適用了)。如果當前數組是對象數組,那麼在PHP5下,其值就是對象的引用,當我們使用foreach對其進行處 理時,情況是這樣的,如下:

  1.首先拷貝一個$element_list,我們把它叫做$element_list_copy。在foreach的處理中,所有處理都是對$element_list_copy數組的處理,並不影響原數組$element_list

  2.得到$element_list_copy中的一個元素,對其進行處 理,此時$element_list_copy中的元素也是一個$Element對象的引用,它和$element_list中的值是一樣的,都是一 個$Element對象的引用,它們兩個指向的是同一塊內存空間,所以對$element_list_copy元素的處理和對$element_list 元素的處理,所操作的數據塊是相同的,也就是$element_list_copy中的元素改變了,$element_list中的元素也會相應地改變, 因爲$element_list_copy和$element_list的元素所指向的是同一塊內存,都是同一個$Element對象。

  這也就是爲什麼經過foreach處理後,對象數組$element_list中的對象的數據發生了改變。千萬要注意PHP5下對象數組及一般數組使用foreach處理的區別,不然就很有可能出現讓人摸不着頭腦的錯誤產生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章