foreach性能更优,因其直接操作哈希表游标、php 7.2+深度优化、避免重复类型检查与指针移动;while配each()已废弃且开销大,仅极小数组且纯写操作时或略快。

foreach 在绝大多数数组遍历场景下性能更好,尤其是 PHP 7.2+;while 配 each() 已废弃且不可靠,手写 current()/next() 循环反而更慢、更易出错。
PHP 7.2+ 中 foreach 性能优势从哪来
foreach 不是简单“复制数组”,而是直接操作哈希表内部游标,跳过键值查找开销;PHP 内部做了大量优化,比如预分配迭代器结构、避免重复类型检查、跳过已 unset() 的桶位。而手写 while 循环(如 while (list($k, $v) = each($arr)))在 PHP 7.2 起已被标记为废弃,运行时会触发 E_DEPRECATED,且每次调用 each() 都要重置/移动内部指针,额外开销明显。
- PHP 7.2+ 的
foreach对空数组、稀疏数组、引用数组都做了路径优化,实测比等效 while 快 10%–30% -
each()在 PHP 8.0+ 彻底移除,代码无法运行 - 即使降级到 PHP 7.4,
foreach的内存占用也更稳定——它不依赖数组的“当前指针位置”,不受reset()或end()干扰
什么情况下 while 可能略快?
仅当满足全部三个条件:数组极小(for 或索引 while 模拟“写时定位”——但这种场景本就不该用 while,而应考虑 for 或直接改用 array_walk()。
- 老资料中提到的“while 写数组更快”,基于 PHP 5.x 的
each()+ 引用行为,现已失效 - 现代 PHP 中,要安全修改原数组元素,正确写法是
foreach ($arr as &$v) { $v .= 'x'; },再unset($v),这比任何 while 手动索引都简洁且快 - 若真在循环中动态增删数组元素(如过滤并重建),
foreach仍比 while 更稳——它自动跳过已被unset()的项,while 容易因指针错位漏项或死循环
别踩这些 while 遍历数组的坑
现在还用 while 遍历数组,大概率是在维护遗留代码,或误信过时机 benchmark。真实风险远不止性能:
-
each()在 PHP 7.2+ 触发警告,PHP 8.0+ 直接报Fatal error: Uncaught Error: Call to undefined function each() - 用
while ($k = key($arr)) { $v = current($arr); next($arr); }必须确保数组指针未被其他函数(如in_array()、array_search())意外移动,否则行为不可预测 - 对引用数组(
$arr = &$other),current()/next()可能返回错误值,而foreach始终按哈希表顺序遍历,与引用状态解耦 - IDE 和静态分析工具(如 PHPStan)无法推断 while 遍历的键类型,
foreach支持完整类型推导
真正需要关注的不是 “while vs foreach”,而是“是否必须在循环中改数组”。如果只是读,foreach 是唯一合理选择;如果要写,优先用引用语法或函数式方法(array_map()、array_filter()),而不是退回 while。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











