PHP 閉包

PHP 閉包我的的簡單理解,就是在匿名函數中經過use直接使用函數以外的變量。閉包

這個函數以外如何定義?函數

例如scala

<?
function total(){
    $total = 0;
    $sub = 0;
    $callback = function($a, $b) use ($total, &$sub){
        //$total 即匿名函數以外的變量
        //&$sub 即匿名函數以外的引用
        $sub = $a+$b+$total;
    };
    $callback(1, 2);
    return $sub;
}
?>

PHP 5.3以後引入了新的閉包語法 即function() use (){}code

function能夠添加參數做爲匿名函數的調用參數對象

use能夠添加參數和引用,這些參數位於匿名函數以外,經過use來使用。string

具體語法以下:io

//定義一個回掉函數
function callback($callback) {  
    $callback();  
}  

//這裏是直接定義一個匿名函數進行傳遞, 在以往的版本中, 這是不可用的.  
callback(function() {  
    print "This is a anonymous function.";  
});
//輸出: This is a anonymous function.



//這裏首先定義了一個閉包, 此次戶口本上有名字了...  
//use, 一個新鮮的傢伙...  
//衆所周知, 閉包: 內部函數使用了外部函數中定義的變量.  
//在PHP新開放的閉包語法中, 咱們就是用use來使用閉包外部定義的變量的.  
//這裏咱們使用了外部變量$msg, 定義完以後, 又對其值進行了改變, 閉包被執行後輸出的是原始值  
//結論: 以傳值方式傳遞的基礎類型參數, 閉包use的值在閉包建立是就肯定了.  
$msg = "Hello, everyone";  
$callback = function () use ($msg) {  
    print "This is a closure use string value, msg is: $msg. ";  
};  
$msg = "Hello, everybody";  
callback($callback);  
//輸出: This is a closure use string value, msg is: Hello, everyone. 


 
//換一種引用方式, 咱們使用引用的方式來use  
//能夠發現此次輸出是閉包定義後的值...  
//這個其實不難理解, 咱們以引用方式use, 那閉包use的是$msg這個變量的地址  
//當後面對$msg這個地址上的值進行了改變以後, 閉包內再輸出這個地址的值時, 天然改變了.  
$msg = "Hello, everyone";  
$callback = function () use (&$msg) {  
    print "This is a closure use string value lazy bind, msg is: $msg. ";  
};  
$msg = "Hello, everybody";  
callback($callback);  
//輸出: This is a closure use string value lazy bind, msg is: Hello, everybody.



//閉包中輸出的是以前被拷貝的值爲Hello, everyone的對象, 後面是對$obj這個名字的一個從新賦值.  
//能夠這樣考慮  
//1. obj是對象Hello, everyone的名字  
//2. 對象Hello, everyone被閉包use, 閉包產生了一個對Hello, everyone對象的引用  
//3. obj被修改成Hello, everybody這個對象的名字  
//4. 注意, 是名字obj表明的實體變了, 而不是Hello, everyone對象, 那天然閉包的輸出仍是前面的Hello, everyone  
$obj = (object) "Hello, everyone";  
$callback = function () use ($obj) {  
    print "This is a closure use object, msg is: {$obj->scalar}. ";  
};  
$obj = (object) "Hello, everybody";  
callback($callback);
//輸出: This is a closure use object, msg is: Hello, everyone.


  
//仍是按照上面的步驟, 循序漸進的來吧:  
//1. obj名字指向Hello, everyone對象  
//2. 閉包產生一個引用指向Hello, everyone對象  
//3. 修改obj名字指向的對象(即Hello, everyone對象)的scalar值  
//4. 執行閉包, 輸出的天然是Hello, everybody, 由於其實只有一個真正的對象  
$obj = (object) "Hello, everyone";  
$callback = function () use ($obj) {  
    print "This is a closure use object, msg is: {$obj->scalar}. ";  
};  
$obj->scalar = "Hello, everybody";  
callback($callback);  
//輸出: This is a closure use object, msg is: Hello, everybody.


 
//閉包引用的是什麼呢? &$obj, 閉包產生的引用指向$obj這個名字所指向的地址.  
//所以, 不管obj怎麼變化, 都是逃不脫的....  
//因此, 輸出的就是改變後的值  
$obj = (object) "Hello, everyone";  
$callback = function () use (&$obj) {  
    print "This is a closure use object lazy bind, msg is: {$obj->scalar}. ";  
};  
$obj = (object) "Hello, everybody";  
callback($callback); 
//輸出: This is a closure use object lazy bind, msg is: Hello, everybody.
相關文章
相關標籤/搜索