为什么应该将函数赋值给一个变量?

3
阅读 php.net 中的匿名函数条目并查看提供的示例时,我遇到了这个部分,其中提到了这些函数的第二个用例:

闭包也可以用作变量的值。

我想知道为什么要将一个方法赋值给一个变量?我在这里试图理解的是这种方法的优势是什么:
$greet = function($name)
{
    echo "Hello $name";
};

$greet('World');
$greet('PHP');

在像这样的一段文字上:

function greet($name) 
{
    echo "Hello $name";
}
greet('World');
greet('PHP');

那它是怎样被证明的呢?它只是一种写代码的另一种方式吗?或者,在更高级的设计中,它会为更具描述性的代码库建立空间吗?

你可以在“映射”中使用它们为值提供函数 $map = array(1 => function() { return "first one";}); echo $map[1](); - Nigel Ren
2
将函数声明为变量允许您通过简单地将该变量重新分配给不同的函数来更改执行流程,而无需更改代码。如果我有一个期望存在全局命名变量用作回调的函数,那么在执行之前现在可以修改此全局变量以更改函数的行为,不必过多考虑。 - isick
2个回答

5
这是一个好问题。匿名函数的问题在于它们通常应该是匿名的。当你将它们赋值给变量时,你给它们命名,这就失去了它们存在的意义。
在简单的示例中,它们与命名函数的工作方式相同:
function named($a) {
    echo 'This is '.$a;
}

$unnamed = function ($a) {
    echo 'This is '.$a;
};

function caller($callee, string $name) {
    $callee($name);
}

caller('named', 'named');
caller($unnamed, 'unnamed');

唯一的区别在于$callee的类型一次是字符串,另一次是函数。 区别: 假设您有这样一种情况,希望将当前作用域捕获到一个函数中,并将其作为回调传递给另一个函数以执行。
$v1 = 2;
$a = function() use($v1) { return $v1; };
// or 
$a = fn() => $v1;
$v1 = 4;

function named($callback) {
    $v1 = 3;
    echo $callback();
}

named($a); //output is 2

使用普通函数,您需要将值作为参数传递给函数。在调用函数时,该值已更改,这意味着您需要在定义函数时自己捕获该值。

可以将闭包分配给变量并不意味着必须这样做。它意味着该函数可以作为一等公民传递。

例如,请考虑以下代码,它捕获了B类中的私有属性,并将其传递到A类内的闭包中:

class A {
    private $someVar = 'Hello world!';

    public function __construct($callback) {
        $callback();
    }
}

class B {
    private $someVar = 'Bogus!';

    public function createCallback() {
        return function () {
            echo $this->someVar;
        };
    }
}

$b = new B();
new A($b->createCallback()); // echo Bogus!

0

您可以在HEREDOC字符串中使用“变量分配”函数:

愚蠢的(未经测试的)例子:

$mult = function( $n ) { return $n * 2; }
$x = 5;

$str = <<<TEXT
$x times two equals {$mult($x)}.
TEXT;

你可以用普通的命名函数做同样的事情。 - Dharman
我已经尝试过了,但出现了错误。即使是内置函数也是如此。实际上,我有一个包装变量的函数,可以返回您传递给它的任何内容,目的是在HEREDOC字符串中使用函数。 - Stephen R
您的测试在该链接上无法正常工作。它会回显“{mult(5)}”。 - Stephen R
1
您的变量保存了函数。在我的例子中,该变量保存了函数名称。 - Dharman
1
@Dharman 不要误会——我喜欢你的回答;但这也是完全合法的用法。我可以随时传入任何我喜欢的函数,带上任何参数。 - Stephen R
显示剩余2条评论

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