Это очень смутило меня, и я не могу найти ответа на этот вопрос. Ясное и простое разъяснение было бы приятным.
Какая разница между параметрами закрытия и ключевым словом "use"?
Ответ 1
Закрытие - это функция, которая вычисляется в своей собственной среде, которая имеет одну или несколько связанных переменных, к которым можно получить доступ при вызове функции. Они происходят из мира функционального программирования, где есть ряд концепций в игре. Закрытия подобны лямбда-функциям, но более умны в том смысле, что они имеют возможность взаимодействовать с переменными из внешней среды, где определено замыкание.
Ключевое слово 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()
для добавления других переменных, которые не являются областью обратного вызова $, но в области среды, в которую она вызывается.
Ответ 2
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 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 make another bank to prove that it has it 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 test bank1 one more time to be sure that bank2 didn't mess with it.
echo $bank1['getBalance'](); // 5 - still 5, as expected.
Возможно, вы заметили, что я использовал справочный оператор &
в этом примере. Если вы еще не знакомы с ними, просто знайте, что, как известно, ссылки трудно понять. Хотя, надеюсь, этот пост в основном имеет смысл сам по себе.