匿名函数 - 在PHP中声明全局变量和使用的区别是什么?

3

在学习PHP中的匿名函数时,我发现了这个:

使用use语法,匿名函数可以使用其封闭作用域中定义的变量。

例如:

    $test = array("hello", "there", "what's up");
    $useRandom = "random";

    $result = usort($test, function($a, $b) use ($useRandom){

                                if($useRandom=="random")
                                    return rand(0,2) - 1;
                                else
                                    return strlen($a) - strlen($b);
                            } 
                    );

为什么我不能像下面这样让$useRandom成为全局变量呢?
    $test2 = array("hello", "there", "what's up");
    $useRandom = "random";

    $result = usort($test, function($a, $b){

                                global $useRandom;

                                if($useRandom=="random")
                                    return rand(0,2) - 1;
                                else
                                    return strlen($a) - strlen($b);
                            } 
                    );

这两种方法有什么区别?

1
在你的第一个示例中,你传递了一个参数,因此$useRandom不是全局的。在第二个示例中,你将变量设为全局。 - Jay Blanchard
1
use 仍然绑定在当前作用域。global 就是真正的全局。 - PeeHaa
3
使用 global 常常是有效的,但仍然存在一些众所周知的问题,例如库之间的名称冲突。 - arkascha
2
请注意,在您的第二个示例中,如果您更改匿名函数内部的 $useRandom,则会更改全局变量的值。在您的第一个示例中,更改匿名函数内部的 $useRandom 将不会改变匿名函数之外的 $useRandom 的值。 - Matt Gibson
2个回答

4

你的例子有些简化。要了解差异,请尝试将您的示例代码包装到另一个函数中,从而在内部回调周围创建一个额外的作用域,该作用域不是全局的。

在以下示例中,$useRandom 在排序回调中始终为null,因为没有名为$useRandom的全局变量。您需要使用use来访问不是全局作用域的外部作用域中的变量。

function test()
{
    $test = array( "hello", "there", "what's up" );
    $useRandom = "random";

    $result = usort( $test, function ( $a, $b ) {

            global $useRandom;
            // isset( $useRandom ) == false

            if( $useRandom == "random" ) {
                return rand( 0, 2 ) - 1;
            }
            else {
                return strlen( $a ) - strlen( $b );
            }
        }
    );
}

test();

另一方面,如果存在全局变量$useRandom,它只能在向下一个作用域中使用use访问。在下一个例子中,$useRandom再次为null,因为它是在两个作用域“更高”的地方定义的,而use关键字仅从当前作用域直接外部导入变量。
$useRandom = "random";

function test()
{
    $test = array( "hello", "there", "what's up" );

    $result = usort( $test, function ( $a, $b ) use ( $useRandom ) {

            // isset( $useRandom ) == false

            if( $useRandom == "random" ) {
                return rand( 0, 2 ) - 1;
            }
            else {
                return strlen( $a ) - strlen( $b );
            }
        }
    );
}

test();

很好地解释了@feeela - Jay Blanchard

2

在很多方面,全局变量都需要小心使用,其中最主要的原因是它可能会导致意外行为:

$foo = 'Am I a global?';

function testGlobal(){
    global $foo;
    echo $foo . ' Yes, I am.<br />';
}

function testAgain() {
    if(isset($foo)) {
        echo $foo . ' Yes, I am still global';
    } else {
        echo 'Global not available.<br />';
    }
}
testGlobal();
testAgain();

在这个例子中,你可能会期望一旦将变量设置为全局变量后,它将在随后的函数中可用。运行此代码的结果表明,情况并非如此:

我是一个全局变量吗?是的。

全局变量不可用。

以这种方式声明全局变量使得该变量在其全局声明的范围内可用(在本例中是函数testGlobal()),但在脚本的一般范围内不可用。
请查看使用全局变量的答案以及为什么这是一个坏主意。

奇怪的假设。我甚至无法想象有人认为导入到一个函数中的变量也会神奇地在其他函数中可用。 - feeela
1
我在多个场合看到过这种情况,特别是对于新的开发人员@feeela。他们认为一旦将变量声明为“global”,它就可以在任何地方使用。 - Jay Blanchard

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