今天在为博客编写文本分析工具时,我发现PHP行为对我来说非常奇怪,并且无法绕过它.在规范化文本时,我试图删除低于最小长度的单词,所以我在我的规范化方法中写了这个:
if ($this->minimumLength > 1) {
foreach ($string as &$word)
{
if (strlen($word) < $this->minimumLength) {
unset($word);
}
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这会在我的数组中留下一些低于允许长度的单词.在我整个班级寻找错误之后,我试了一下:
if ($this->minimumLength > 1) {
foreach ($string as $key => $word)
{
if (strlen($word) < $this->minimumLength) {
unset($string[$key]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
瞧!这非常有效.现在,为什么会发生这种情况?我查看了PHP文档,它说明:
如果一个PASSED BY REFERENCE变量在函数内部未设置(),则只销毁局部变量.调用环境中的变量将保留与调用unset()之前相同的值.
是否foreach充当这里的calling environment,因为它有它自己的范围是什么?
不,这里没有函数调用,也没有通过引用传递变量(您只是在迭代期间通过引用捕获)。
当您通过引用进行迭代时,迭代变量是原始变量的别名。当您使用此别名来引用原始值并修改其值时,更改将在正在迭代的数组中保持可见。
但是,当您unset使用别名时,原始变量并没有被“破坏”;别名只是从符号表中删除。
foreach ($string as $key => &$word)
{
// This does not mean that the word is removed from $string
unset($word);
// It simply means that you cannot refer to the iteration variable using
// $word from this point on. If you have captured the key then you can
// still refer to it with $string[$key]; otherwise, you have lost all handles
// to it for the remainder of the loop body
}
Run Code Online (Sandbox Code Playgroud)