全局变量 vs. 局部变量

6

好的,我不确定我是否正确理解了这个概念(我正在学习PHP)。如果我理解正确: 全局变量可以在同一文档中的任何地方引用,或者在使用“include”链接的文档中引用。本地变量只能在它们所在的函数中引用。

好的,如果我理解正确(这也是我发布的半个原因,以确保我理解正确),那么是否真的需要本地变量呢?我的意思是,如果每个用户定义自己的变量并需要将它们全部保存,我可以看到这是有用的...但是,我认为使用数据库会更简单。什么情况下我需要使用本地变量呢?

6个回答

9

你的问题在询问“本地变量”的必要性这一点上变得没有意义。总体来说,你应该尽可能避免使用全局变量。

我经常写一些工具/网站应用程序,并且只有两三个我自己的全局变量,用于启动实际应用程序。

考虑以下情况:

$db = new PDO($conn, $usr, $pass);
function select(array $fields, $tbl, $where = '')
{
    global $db;//use the global variable
    return $db->query('SELECT '.implode(', ', $fields).' FROM '.$tbl.' WHERE '.$where);
}

就本身而言,你可能会认为这段代码一直可以正常运行。很清楚 $db 是什么,因此此处没有明显的错误。
但是,假设您包含了另外几个使用相同 $db 变量的文件,并且其中一个文件存在错误导致 $db 被重新赋值:

$db = 'I used to be a PDO instnace';
select(array('*'), 'tbl');

这将显示一个错误,指向读取return $db->query();的行,并且会说一些类似于"trying to call method of non-object"的内容。

祝你调试好运!$db重新赋值在哪里?除了逐步过滤您的代码之外,没有其他方法可以知道。

声明所有变量为全局变量就像每晚将您的钱包放在人行道上一样。

它可能仍然在你上次离开的地方,但很有可能它的状态(或值)已经被其他实体/人或代码显着更改,他们可能已经像自己的一样使用了您的钱包(或变量),毫不知情地将其留到未来。编写类或函数时,您还将使用该代码的同事称为用户。因此,即使他们没有恶意,全局变量也是一种等待发生的意外。

顺便说一句,函数参数局部变量,所以我相信您已经在使用它们,只是不知道而已。

最好将select函数定义如下:

function select(PDO $connection, array $fields, $tbl = 'tbl', $where = null)
{
    $query = 'SELECT '.implode(', ', $fields).' FROM '.$tbl;
    $query .= $where !== null ? ' WHERE '.$where : '';
    return $connection->query($query);
}

在这个函数中,我创建了一个本地变量,以使代码更易读/易维护。就像我说的,所有参数也都是本地变量,因此在此函数返回后,为容纳它们所持有的值而分配的任何内存都可以被释放。当您使用全局变量时,垃圾回收器无法发挥作用,因为变量仍然在作用域内,并且可能会在代码后面进一步使用。内存只有在脚本完成运行后才会被释放。
全局变量告诉垃圾回收器“等一下”,每次尝试释放内存时,因为脚本可能稍后需要该变量。充满全局变量的代码就像囤积者写的东西。
全局变量(全局范围内的变量)会导致混乱的代码,因为您尝试避免名称冲突,您将发现自己声明变量,例如 $i_for_looping_over_array1 = 0;
好吧,那可能有点极端,但您最终会伪命名空间化您的变量,因此为什么不使用适当的命名空间、作用域、类等呢?
使用 global 关键字会减慢速度
每当您在函数内部使用 global 关键字时,您实际上是在说:查找名为 $someName 的变量,它可以在任何地方。将同一变量作为参数传递是告诉函数使用此变量。
当传递对象时,您实际上传递了对该对象的引用(即其地址),因此不需要查找。原始数据类型会被复制,因此也没有查找。
把自己想象成一个调酒师。你宁愿在哪里工作?在 Pub AllIsGlobalHere 中,在那里,你的老板在第一天就说:“如果顾客要什么东西,瓶子可能在任何地方,酒窖、地板或右上角的橱柜”,还是在 Pub CheckTheArguments 中。后者是你直接进入的地方,当顾客要求一杯啤酒时,你的老板和/或顾客会乐意指出应该参考哪个龙头。

2

本地变量是封装的必要条件,这是编程中的良好实践。

全局变量实际上是一种不好的实践,因为变量可以在应用程序的任何地方被改变,并且相信我,如果你有多个包含多个包含的情况下,很难调试为什么变量的值不是预期值...

如果您需要使用全局变量,也许您应该考虑使用单例或将变量作为参数传递给需要它的函数。


摒弃单例!此外,楼主仍在学习 PHP,并且正在学习作用域,因此我认为他还没有到编写自己的类的阶段。 - Elias Van Ootegem
好的,我也不喜欢单例模式,但它是全局变量的一种替代方案。 - m4t1t0

1
在编程中,有许多情况下你只需要在一个隔离的上下文中使用变量。计数器、函数参数以及用于存储计算过程中的临时结果等变量,在整个应用程序中都没有任何意义。 此外,还有递归函数的特殊情况。本地变量将为递归函数的每个实例获取其自己的独特地址,这是递归正常工作所必需的。 然而,在PHP应用程序中,建议尽可能避免使用全局变量。

0
什么情况下我会想要使用局部变量?
局部变量是在本地作用域(函数)内定义的变量,这些变量仅在该作用域内可用,而在外部不可用,例如:
$foo = 'foo';
function bar(){
 $foo = 'bar';
}

echo $foo; //prints foo

例如,您可以看到相同的变量名称可以在本地范围内使用而不会产生任何影响。

0

如果您只使用全局变量,那么每次需要新的计数器时都需要给它一个新名称,哈哈。

变量的可见性对于封装是必要的:变量只能被您想要访问它的对象所影响。例如:

class Person{
  private $_money;
  public function rob(){
    return $this->_money;
  }
}

只有 Person 类的对象才能操作他的钱,所以如果你想得到它们,你必须拿上面具和枪。


0

有几个理由更喜欢使用局部变量而不是全局变量:

变量占用内存。如果每个变量都在全局作用域中,那将占用大量内存。局部变量只在其作用域内存在,因此它们只临时使用内存,然后该内存再次被释放... 因此更好的内存使用是一个很好的论点。

如果所有变量都是全局的,那么函数A和函数B可能都会更新一个变量,但是两者都不知道对方已经改变了它,这可能导致你没有意识到一个函数已经改变了一个值,并且假设它在另一个函数中仍然有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接