闭包参数和“use”关键字有什么区别?

2022-08-30 20:41:40

这让我非常困惑,我似乎找不到这个问题的答案。一个清晰而简单的澄清会很好。


答案 1

创建闭包函数时捕获变量use statement

常规函数参数在调用函数时捕获

请注意,我区分了和那里。variablevalue

function makeAnAdder($leftNum) {
    // Notice that *each time* this makeAnAdder function gets called, we 
    // create and then return a brand new closure function.
    $closureFunc = function($rightNum) use ($leftNum) {
        return $leftNum + $rightNum;
    };

    return $closureFunc;
}

$add5to = makeAnAdder(5);
$add7to = makeAnAdder(7);

echo $add5to(10); // 15
echo $add7to(1); // 8

如果有一种方法可以检查函数的“源代码”,它将如下所示:$add5to

function($rightNum) {
    return 5 + $rightNum;
}

我想你可以说闭包函数记住的值。$leftNum

我想进一步强调,允许您维护变量,而不仅仅是变量在某个时候具有的值的副本。为了澄清我的想法:将变量视为一个小盒子,它可以在任何时刻包含单个值,并且该值可以更改。并且,您可以使另一个变量指向该框,以便可以更新框中的值,或读取其中的当前值。use statementreference

通常,在函数内创建的局部变量在函数返回后将不复存在。但是,闭包函数可以保持对该变量的引用,并导致该局部变量即使在函数返回后仍然存在 - 这就是闭包函数的真正功效。它允许您仅用少量代码模拟类的某些行为(实例变量)。

这是一个更高级的例子,可能需要一些深入的思考来理解行为的细节。

function makeBankAccount() {
    // Each time this makeBankAccount func is called, a new, totally
    // independent local variable named $balance is created.
    $balance = 0;

    // Also, on each call we create 2 new closure functions, $modifyBalance, and $getBalance
    // which will hold a reference to the $balance variable even after makeBankAccount returns.
    $modifyBalance = function($amount) use (&$balance) {
        $balance += $amount;
    };

    $getBalance = function() use (&$balance) {
        return $balance;
    };

    // return both closure functions.
    return ['modifyBalance' => $modifyBalance, 'getBalance' => $getBalance];
}

// Let's prove that bank1 works by adding 5 to the balance by using the first
// function, then using the other function to get the balance
// from the same internal variable.
$bank1 = makeBankAccount();
$bank1['modifyBalance'](5);
echo $bank1['getBalance'](); // 5 - it works.

// Now let's make another bank to prove that it has it's own independent internal $balance variable.
$bank2 = makeBankAccount();
$bank2['modifyBalance'](10);
echo $bank2['getBalance'](); // 10 - as expected. It would have printed 15 if bank2 shared a variable with bank1.

// Let's test bank1 one more time to be sure that bank2 didn't mess with it.
echo $bank1['getBalance'](); // 5 - still 5, as expected.

您可能已经注意到,我在此示例中使用了引用运算符。如果您还不熟悉它们,只需知道参考文献很难理解即可。虽然,我希望这篇文章本身就有意义。&


答案 2

闭包是在自己的环境中计算的函数,它具有一个或多个绑定变量,在调用函数时可以访问这些变量。它们来自函数式编程世界,那里有许多概念在起作用。闭包类似于 lambda 函数,但从某种意义上说,它们更智能,因为它们能够与定义闭包的外部环境中的变量进行交互。

use() 关键字允许您从函数环境外部的函数内部导入变量。要从外部环境导入的变量在闭包函数定义的 use 子句中指定。默认情况下,它们是按值传递的。因此,假设该函数没有参数,但您不希望它使用您已经拥有的变量。

$string = "Hello World!";
$closure = function() use ($string) { echo $string; };

当您需要创建一个必须在其他地方用作回调的函数并且只能具有定义的参数时,这很有用。use() 关键字允许您使用其他变量,而不是作为函数参数传递的变量。例如,在 php.net 示例:http://php.net/manual/en/functions.anonymous.php

public function getTotal($tax)
    {
        $total = 0.00;

        $callback =
            function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };

        array_walk($this->products, $callback);
        return round($total, 2);
    }

$callback必须只有两个参数,因为array_walk只允许这么多:

通常,funcname 采用两个参数。数组参数的值是第一个,键/索引是第二个。

那么我们能做些什么呢?我们调用添加其他变量,这些变量不是$callback的作用域,而是在调用它的环境的作用域中。use()


推荐