今天在为博客开发文本分析工具时,我发现PHP行为对我来说非常奇怪,而且无法绕过它。在规范化文本时,我试图删除低于最小长度的单词,所以我在我的规范化方法中写了这个:
if ($this->minimumLength > 1) {
foreach ($string as &$word)
{
if (strlen($word) < $this->minimumLength) {
unset($word);
}
}
}
奇怪的是,这会在我的数组中留下一些低于允许长度的单词。在我整个班级寻找错误后,我试了一下:
if ($this->minimumLength > 1) {
foreach ($string as $key => $word)
{
if (strlen($word) < $this->minimumLength) {
unset($string[$key]);
}
}
}
瞧!这非常有效。现在,为什么会发生这种情况?我查看了PHP Documentation并说明了:
如果在函数内部取消设置了一个被PASSED BY REFERENCE的变量,则只销毁局部变量。调用环境中的变量将保留与调用unset()之前相同的值。
foreach
此处是calling environment
,因为它有自己的范围吗?
答案 0 :(得分:2)
不,这里没有函数调用,并且没有通过引用传递变量(您只是在迭代期间通过引用捕获)。
当您通过引用迭代时,迭代变量是原始的别名。当您使用此别名来引用原始别名并修改其值时,更改将在要迭代的数组中保持可见。
但是,当您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
}
答案 1 :(得分:1)
当您在if语句中调用unset($word)
时,您正在删除$word
变量本身,而不对数组$string
进行任何更改。