foreach 是 PHP 遍歷數組/對象的首選結構,但其「值拷貝」語義與 for 循環的下標訪問存在本質差異,理解這一點對避免邏輯錯誤、優化性能至關重要。
| 特性 | foreach | for + 下標 |
|---|---|---|
| 操作對象 | 數組拷貝(PHP 5+) | 原數組引用 |
| 修改原數組 | 需用 &$value | 直接修改 $arr[$i] |
| 內部指針 | 不影響 current() 等 | 無內部指針概念 |
| 遍歷對象屬性 | 支援(PHP 5+) | 需配合 get_object_vars() |
抑制錯誤 @ | 不支援 | 支援 |
<?php
$arr = [1, 2, 3, 4];
// 1. 預設值拷貝:修改 $value 不影響原數組
foreach ($arr as $value) {
$value *= 2;
}
var_dump($arr); // [1, 2, 3, 4] 未變
// 2. 引用修改:使用 &$value 直接操作原數組元素
foreach ($arr as &$value) {
$value *= 2;
}
var_dump($arr); // [2, 4, 6, 8] 已修改
// 3. 最佳實踐:引用循環後 unset 解除引用,防止後續誤用
foreach ($arr as &$value) { /* ... */ }
unset($value); // 重要!
?>
foreach 對數組進行按值拷貝時使用寫時複製(COW)機制,未修改時幾乎零開銷foreach 比 for 更快(避免重複哈希查找)for 配合逆序遍歷更安全Traversable 接口實現 Iterator 或 IteratorAggregate 接口的對象可直接 foreach 遍歷,這是構建集合類庫的基礎。
class DataCollection implements IteratorAggregate {
private $data = [];
public function getIterator() {
return new ArrayIterator($this->data);
}
}
$col = new DataCollection();
foreach ($col as $item) { /* ... */ }
foreach ($arr as $v),語義清晰、性能優foreach ($arr as &$v) + unset($v)for ($i = count($arr)-1; $i >= 0; $i--)foreach ($arr as $k => $v)掌握 foreach 的拷貝語義與引用機制,是寫出無 Bug、高性能 PHP 代碼的關鍵基本功。