与for()(在每次迭代中对每条指令进行评估)相比,foreach() 在开头获取array,然后移动指针以遍历它:
第一种形式循环遍历由array_expression 给出的数组。在每次迭代中,当前元素的值被分配给 $value,内部数组指针前移一个(因此在下一次迭代中,您将查看下一个元素)。
强调我的
所以你的函数只被调用一次。您可以通过查看操作码看到这种行为。
Without assignment:
<?php
function find() {
return [1, 2, 3, 4, 5, 6, 7, 8];
}
foreach (find() as $n) {
echo $n.PHP_EOL;
}
操作码:
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > NOP
7 1 INIT_FCALL 'find'
2 DO_FCALL 0 $1
3 > FE_RESET_R $2 $1, ->8
4 > > FE_FETCH_R $2, !0, ->8
8 5 > CONCAT ~3 !0, '%0A'
6 ECHO ~3
7 > JMP ->4
8 > FE_FREE $2
9 9 > RETURN 1
还有with assignment:
<?php
function find() {
return [1, 2, 3, 4, 5, 6, 7, 8];
}
$f = find();
foreach ($f as $n) {
echo $n.PHP_EOL;
}
操作码:
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > NOP
6 1 INIT_FCALL 'find'
2 DO_FCALL 0 $2
3 ASSIGN !0, $2
7 4 > FE_RESET_R $4 !0, ->9
5 > > FE_FETCH_R $4, !1, ->9
8 6 > CONCAT ~5 !1, '%0A'
7 ECHO ~5
8 > JMP ->5
9 > FE_FREE $4
9 10 > RETURN 1
如您所见,唯一的区别是ASSIGN 指令,即对$f 的赋值。
所以这主要是一个可读性问题。在我看来,将方法的返回值分配到具有适当名称的变量中更具可读性。然而,鲍勃叔叔在 Clean Code 中却相反:
循环的控制变量通常应该在循环语句中声明,就像来自同一来源的这个可爱的小函数一样。
public int countTestCases() {
int count= 0;
for (Test each : tests)
count += each.countTestCases();
return count;
}