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

时间:2012-05-21 21:23:46

标签: php closures anonymous-function

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

2 个答案:

答案 0 :(得分:25)

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.

您可能已经注意到我在此示例中使用了reference operator &。如果你还没有熟悉它们,只要知道参考文献很难理解。虽然,我希望这篇文章本身最有意义。

答案 1 :(得分:22)

闭包是一个在自己的环境中计算的函数,它有一个或多个绑定变量,可以在调用函数时访问它们。它们来自功能编程世界,其中有许多概念在起作用。闭包就像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范围的其他变量,但是在调用它的环境范围内。