Это меня очень смутило, и я не могу найти ответа на этот вопрос. Ясное и простое разъяснение было бы неплохо.
Закрытие – это функция, которая оценивается в ее собственной среде, которая имеет одну или несколько связанных переменных, к которым можно получить доступ при вызове функции. Они происходят из мира функционального программирования, где есть ряд концепций в игре. Закрытия подобны лямбда-функциям, но более умны в том смысле, что они имеют возможность взаимодействовать с переменными из внешней среды, где определено замыкание.
Ключевое слово 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, но в области среды, в которую он вызван.
Оператор use statement
захватывает переменную во время создания функции закрытия .
Регулярные аргументы функции фиксируют значение при вызове функции.
Обратите внимание, что я различал variable
и value
там.
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.
Возможно, вы заметили, что я использовал ссылочный оператор &
в этом примере. Если вы еще не знакомы с ними, просто знайте, что, как известно, ссылки трудно понять. Хотя, надеюсь, этот пост в основном имеет смысл сам по себе.