對比 foreach、while(list()=each())、for 三種遍歷 50,000 元素一維數組的性能,實測 foreach 最快 (0.008s),for 次之 (0.023s),while/each 最慢 (0.054s)。解析底層原理:foreach 操作數組副本 (C 級循環),while/each 移動內部指針 (PHP 級循環 + 函數調用開銷)。
$arr = [];
for ($i=0; $i<50000; $i++) $arr[] = $i * rand(1000,9999);
function microtime_float() {
list($usec, $sec) = explode(' ', microtime());
return (float)$usec + (float)$sec;
}
// for
$t = microtime_float();
for ($i=0; $i$v) $v = $v;
echo 'foreach: ' . round(microtime_float()-$t, 7) . "s\n";
foreach: 0.0085s
for: 0.0228s
while: 0.0545s
| 方式 | 底層機制 | 優勢/劣勢 |
|---|---|---|
foreach | 複製數組指針結構 (HashTable Bucket 指針陣列),C 循環遍歷副本 | 最快、語法最簡、不影響原數組指針、PHP 5+ 支持對象屬性遍歷 |
for | 整數索引遞增,count() 每次調用 (優化:預存長度) | 僅適用連續整數索引,需手動管理索引邊界 |
while/each | each() 返回當前鍵值並前移內部指針,PHP 函數調用開銷大 | 最慢、改變原數組指針、PHP 7.2 棄用 each()、PHP 8.0 移除 |
foreach:所有場景通用、性能最優、語義清晰。foreach ($arr as $i => $v) 直接獲取鍵。foreach ($arr as &$v) 循環後 unset($v) 釋放引用。foreach ($arr as $v) 不用 & 避免分離副本開銷。count() 在循環條件中:預存 $len = count($arr)。foreach 複製數組機制。foreach 不再複製整個數組,而是複製 HashTable 指針陣列,性能大幅提升。each() 拋出棄用警告。each(),while(list()=each()) 徹底不可用。現代 PHP (7.4+) 開發,**無理由不使用 foreach** 作為默認遍歷方式。