图片alt

最近在公司比较忙,以前有空闲的时候没有发现的东西,反而再忙的时候会加深体会。所以就动了心思准备写一个 php 细节补全的系列,不知道能写多少,慢慢来吧,这个就是第一篇了。

其实,平时我个人觉得再使用引用的时候机会并没有那么多,但是呢,引用这个东西是绝对不可以忽略的。

引用平时就我个人来说使用的场景有如下几个:

  • 有批量处理数组数据的时候会使用引用,这样再方法里面就不用在单独返回了,比较省事
  • 再有递归调用的时候也会使用,但是使用的时候需要注意小心踩坑

剩下的貌似就不是很多了,但是这两天看过几个面试题,让我平时没注意的一些东西或者说没有深入考虑的东西,有了更深入的理解。

先看下面这个题:

1
2
3
4
5
6
7
8
9
/**
 * 下面的循环执行后数组的结果是多少
 */

$arr = ['a', 'b', 'c'];

foreach ($arr as $key => $value) {
    $value = &$arr[$key];
}

先不说结果,先说说平时我们没有注意过的 foreach是如何执行的吧:

  • 首先执行到这里foreach ($arr as $key => $value) 到这里,系统会从数组里面取出当前的元素,把索引赋值给 $key,把值赋值给value, 如果代码没写$key => $value,这种形式,而是只有$key就只会把值赋值给$key
  • 然后进入循环体,执行循环体的代码
  • 重新回到 for 那行,然后进入循环体。一直这样下去,直到循环结束

上面的就是我个人总结的foreach的执行流程。很多时候我们并没有注意在 foreach 那行的 $key$value 赋值的过程,所以再遇到引用问题的时候就毛骨悚然了。

好了,下面再说说我所理解的引用,引用就是跟随所引用的变量,当修改任何一个变量的值的时候都会同步修改。可能说的很简单,但是刚才我想了一个更复杂的说法,发现很绕,我自己都理解不了,所以,最终还是用这个简单的版本来说明把。再后续的代码说明中,再具体说。

好了,下面我们就进入上面代码代码一行一行的解释了

1
2
3
4
5
$arr = ['a', 'b', 'c'];

foreach ($arr as $key => $value) {
    $value = &$arr[$key];
}

经过数组的赋值后,我们首先执行到了 foreach ($arr as $key => $value) { 这行代码,我们首先从数组里面取出第一个元素,然后把第一个元素的索引 0 赋值给 $key,再把这个元素的值 a 赋值给 $value。 这样这样代码就执行完毕了,此时数组 $arr 的值还是 abc, $key 的值是 0,$value 的值是 a。

然后我们执行到了 $value = &$arr[$key]; 这行代码,这行代码用到了索引,我们把 $value 指向到了数组的第一个元素。注意,这里其实并不是赋值,而是把 $value 指向到了数组第一个元素的位置,虽然我们正常使用可以获取到值,但是实际上并不是一个赋值的操作,可以理解为关联的关系,$value 和数组的第一个元素关联起来了,当我们修改 $value 的时候数组第一个元素的值也会被同步修改。

这样循环体的代码也执行完毕了,我们又回到了 foreach ($arr as $key => $value) { 这行代码中,这时我们从数组中取出了第二个元素,然后把元素的索引 1 赋值给 $key,把数组的值 b 赋值给 $value。到这依然跟上面一样,但是需要注意的是,此时 $value 是有关联关系的,他跟数组的第一个元素关联起来了,此时赋值给 $value 就会修改关联关系中数组第一个元素的值,所以此时 $value 的值是 b 了,同时数组第一个元素的值也变为了 b。这行代码执行完毕,这时数组的值是 bcc,$key 是 1 ,$value 指向的是数组第一个元素 数组第一个元素的值是 b。

解析来又进入了循环体,又是使用了索引,对了这里注意的是索引跟赋值有些不一样,赋值就是直接改变值了,但是索引操作可以理解为是一个箭头指向了另一个物体。我们把 $value 关联到了数组的第一个元素。

紧接着有进入了 foreach 这行,此时我们取出了第三个元素,把元素的索引 2 赋值给 $key,然后把数组的值 c 赋值给 $value。不巧了此时 $value 关联了数组的第二个元素,所以此时赋值也会改变数组的第二个元素的值。所以此时数组 $arr 的值是 bcc,$key 的值是2,$value 关联了数组的第二个元素 值是 c

这是进入循环体,把 $value 关联到了数组的第三个元素。

注意,这里还有一步,依然会回到 foreach 这行,我们继续从数组取值,发现数组已经没有元素可以获取了,所以退出循环,很多时候我们也会忽略最后这步的,虽然没什么实际上的影响,但是我们也最好要记住这个最后一步。

好了,乱七八糟的说完了,起码我自己是明白了,希望看到的人也能有所启发,如果又不懂的,只能说抱歉了,评论系统一个接一个的挂了,你们也没地方评论,自己仔细看看引用的文档吧,然后再用笔纸画画可能就明白了呢。

再来一个题把

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/**
 * 下面的循环执行后数组的结果是多少
 */

$arr = ['a', 'b', 'c'];

foreach ($arr as $key => &$value) {

}
var_dump($arr);
foreach ($arr as $key => $value) {

}
var_dump($arr);

这个我就不细说了,大家思考一下,我简单说一下吧,经过第一个循环以后,$value 关联了数组的最后一个元素,那么当执行第二个循环的时候会怎样呢?

今天就到这吧,感觉很久不写东西,文笔果然不行了啊