19

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

4

2 回答 2

26

创建闭包函数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 statement允许您维护一个reference变量而不仅仅是该变量在某个时刻所具有的值的副本。澄清我的想法:将变量想象成一个小盒子,它可以在任何时刻包含单个值,并且可以更改该值。并且,您可以使另一个变量指向该框,以便您可以更新框中的值,或读取其中的当前值。

通常,在函数内创建的局部变量会在函数返回后不复存在。但是,闭包函数可以维护对该变量的引用,并使该局部变量即使在函数返回后仍然存在——这就是闭包函数的真正威力。它可以让你模仿一个类的某些行为(实例变量),只需要一点点代码。

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

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.

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

于 2012-05-21T21:51:59.613 回答
24

闭包是在自己的环境中评估的函数,它具有一个或多个绑定变量,在调用函数时可以访问这些变量。它们来自函数式编程世界,其中有许多概念在起作用。闭包类似于 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 有两个参数。数组参数的值是第一个,键/索引是第二个。

所以,我们能做些什么?我们调用use()添加其他变量,这些变量不是 $callback 的范围,而是在它被调用的环境范围内。

于 2012-05-21T21:33:05.883 回答