PHP에서 폐쇄란 무엇이며 왜 "사용" 식별자를 사용하는가?
몇 가지 .PHP 5.3.0
사이트상에서 꽤 재미있는 코드를 발견했습니다.
public function getTotal($tax)
{
$total = 0.00;
$callback =
/* This line here: */
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);
}
이것에 대해 아는 사람 있나요?서류가 있나요?그리고 사악해 보이는데, 꼭 사용해야만 하나요?
더 간단한 대답입니다.
function ($quantity) use ($tax, &$total) { .. };
- 닫힘은 변수에 할당된 함수이므로 변수를 전달할 수 있습니다.
- 폐쇄는 별도의 네임스페이스이며 일반적으로 이 네임스페이스 외부에 정의된 변수에 액세스할 수 없습니다.다음으로 use 키워드를 나타냅니다.
- use를 사용하면 폐쇄 내부의 후속 변수에 액세스(사용)할 수 있습니다.
- use는 조기 바인딩입니다.즉, 닫힘을 정의할 때 변수 값이 복사됩니다.그래서 수정하는 중
$tax
개체와 같은 포인터가 아닌 한 폐쇄 내부의 외부 효과는 없습니다. - 하다 보면 '를 로 할 수 요.
&$total
하면 " "의 값을 할 수$total
외부 효과가 있으면 원래 변수의 값이 변경됩니다. - 폐쇄 내부에서 정의된 변수도 폐쇄 외부에서 액세스할 수 없습니다.
- 폐쇄 및 기능은 동일한 속도를 가집니다.예, 스크립트에서 모두 사용할 수 있습니다.
@Mytskine이 지적한 바와 같이 아마도 가장 상세한 설명은 폐쇄에 관한 RFC일 것입니다.(이것에 대해 그를 지지해 주세요.)
이것이 PHP가 폐쇄를 표현하는 방법입니다.이것은 전혀 악하지 않고 사실 꽤 강력하고 유용하다.
가 로컬 수 있도록 경우 ""는 "캡처"가 됩니다).$tax
에 대한 $total
의 범위를 벗어나 그을 보존합니다( (이 )의 경우).$total
에 the to to 언급$total
그 자체)를 익명 기능 자체 내의 상태로 합니다.
function () use () {}
PHP php php php php php php php php php php 。
use
스코프 변수인 "Can't can't access the parent variable, "Cannot access the parent scope variable" (부모 스코프 변수)
$s = "hello";
$f = function () {
echo $s;
};
$f(); // Notice: Undefined variable: s
$s = "hello";
$f = function () use ($s) {
echo $s;
};
$f(); // hello
use
된 시점부터이며, 함수가 입니다.
$s = "hello";
$f = function () use ($s) {
echo $s;
};
$s = "how are you?";
$f(); // hello
use
와 &
$s = "hello";
$f = function () use (&$s) {
echo $s;
};
$s = "how are you?";
$f(); // how are you?
클로징은 아름답다!익명의 함수에 수반하는 많은 문제를 해결하고, 매우 우아한 코드를 가능하게 합니다(적어도 php에 대해 이야기하는 한).
javascript 프로그래머는 바인드 변수가 명시적으로 정의되어 있지 않기 때문에 항상 닫힘을 사용합니다.그것이 php에서 "사용"의 목적입니다.
위의 사례보다 더 나은 실제 사례들이 있다.예를 들어, 다차원 배열을 하위 값으로 정렬해야 하는데 키가 변경됩니다.
<?php
function generateComparisonFunctionForKey($key) {
return function ($left, $right) use ($key) {
if ($left[$key] == $right[$key])
return 0;
else
return ($left[$key] < $right[$key]) ? -1 : 1;
};
}
$myArray = array(
array('name' => 'Alex', 'age' => 70),
array('name' => 'Enrico', 'age' => 25)
);
$sortByName = generateComparisonFunctionForKey('name');
$sortByAge = generateComparisonFunctionForKey('age');
usort($myArray, $sortByName);
usort($myArray, $sortByAge);
?>
warning: 테스트되지 않은 코드(php5.3 atm은 설치되어 있지 않습니다만, 이것과 비슷합니다.
단점이 하나 있습니다.많은 php 개발자들이 폐쇄로 맞서면 조금 무력해질 수 있습니다.
폐쇄의 장점을 좀 더 이해하기 위해 다른 예를 제시하겠습니다. 이번에는 자바스크립트로요.그 중 하나는 스코핑과 브라우저 고유의 비동기성입니다.특히라면window.setTimeout();
(또는 -disclos)setTimeout에 함수를 전달하지만 매개 변수를 제공하면 코드가 실행되기 때문에 매개 변수를 지정할 수 없습니다.
function getFunctionTextInASecond(value) {
return function () {
document.getElementsByName('body')[0].innerHTML = value; // "value" is the bound variable!
}
}
var textToDisplay = prompt('text to show in a second', 'foo bar');
// this returns a function that sets the bodys innerHTML to the prompted value
var myFunction = getFunctionTextInASecond(textToDisplay);
window.setTimeout(myFunction, 1000);
myfunction은 미리 정의된 파라미터의 종류를 가진 함수를 반환합니다.
솔직히 5.3 이후 php와 익명 함수/파워드를 더 좋아합니다.네임스페이스가 더 중요하긴 하지만 덜 섹시해
Zupa는 폐쇄를 '사용'으로 설명하고 Early Binding과 '사용' 변수 참조의 차이를 잘 설명했습니다.
그래서 변수의 초기 바인딩(= 복사)으로 코드 예를 만들었습니다.
<?php
$a = 1;
$b = 2;
$closureExampleEarlyBinding = function() use ($a, $b){
$a++;
$b++;
echo "Inside \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "Inside \$closureExampleEarlyBinding() \$b = ".$b."<br />";
};
echo "Before executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "Before executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";
$closureExampleEarlyBinding();
echo "After executing \$closureExampleEarlyBinding() \$a = ".$a."<br />";
echo "After executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";
/* this will output:
Before executing $closureExampleEarlyBinding() $a = 1
Before executing $closureExampleEarlyBinding() $b = 2
Inside $closureExampleEarlyBinding() $a = 2
Inside $closureExampleEarlyBinding() $b = 3
After executing $closureExampleEarlyBinding() $a = 1
After executing $closureExampleEarlyBinding() $b = 2
*/
?>
변수를 참조하는 예(변수 앞에 '&' 문자를 표시);
<?php
$a = 1;
$b = 2;
$closureExampleReferencing = function() use (&$a, &$b){
$a++;
$b++;
echo "Inside \$closureExampleReferencing() \$a = ".$a."<br />";
echo "Inside \$closureExampleReferencing() \$b = ".$b."<br />";
};
echo "Before executing \$closureExampleReferencing() \$a = ".$a."<br />";
echo "Before executing \$closureExampleReferencing() \$b = ".$b."<br />";
$closureExampleReferencing();
echo "After executing \$closureExampleReferencing() \$a = ".$a."<br />";
echo "After executing \$closureExampleReferencing() \$b = ".$b."<br />";
/* this will output:
Before executing $closureExampleReferencing() $a = 1
Before executing $closureExampleReferencing() $b = 2
Inside $closureExampleReferencing() $a = 2
Inside $closureExampleReferencing() $b = 3
After executing $closureExampleReferencing() $a = 2
After executing $closureExampleReferencing() $b = 3
*/
?>
최근 몇 년 동안 PHP는 AST 인터프리터를 정의하고 PHP 인터프리터는 평가 부분에서 파서를 분리했습니다.클로징이 도입되는 동안 PHP의 파서는 평가와 매우 연계되어 있습니다.
따라서 닫힘이 PHP에 처음 도입되었을 때 인터프리터는 아직 해석되지 않았기 때문에 닫힘에서 어떤 변수를 사용할지 알 수 있는 방법이 없습니다.따라서 사용자는 젠드가 해야 할 숙제를 하면서 명시적인 Import를 통해 젠드 엔진을 만족시켜야 합니다.
이것은 PHP에서 소위 말하는 간단한 방법입니다.
언급URL : https://stackoverflow.com/questions/1065188/in-php-what-is-a-closure-and-why-does-it-use-the-use-identifier
'source' 카테고리의 다른 글
MySQL 쿼리에서 타임스탬프를 현재 날짜로 변환 (0) | 2022.09.25 |
---|---|
WordPress를 사용하여 URL에서 추가 변수를 전달하는 방법 (1) | 2022.09.25 |
Gradle - 기본 매니페스트 속성 없음 (1) | 2022.09.25 |
MySQL에서 중첩된 트랜잭션이 허용됩니까? (0) | 2022.09.25 |
값을 한 필드에서 두 필드로 분할 (1) | 2022.09.25 |