成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【modernPHP專題(8)】匿名函數(shù)和閉包

junnplus / 2663人閱讀

摘要:匿名函數(shù)輸出可以直接將匿名函數(shù)進(jìn)行傳遞。報錯,找不到變量之所以稱為副本,是因?yàn)橥ㄟ^閉包傳值到匿名函數(shù)內(nèi)的變量值也是不能改變。該方法使用了一個作為回調(diào)函數(shù)。

匿名函數(shù)
// Example1
$func = function( $param ) {
    echo $param;
};
$func( "some string" );//輸出:some string

// Example2
function callFunc( $func ) {
    $func( "some string" );
}
$printStrFunc = function( $str ) {
    echo $str;
};
callFunc( $printStrFunc );

//可以直接將匿名函數(shù)進(jìn)行傳遞。如果你了解js,這種寫法可能會很熟悉
callFunc( function( $str ) {
    echo $str;
} );
閉包

PHP在默認(rèn)情況下,匿名函數(shù)內(nèi)不能調(diào)用所在代碼塊的上下文變量,而需要通過使用use關(guān)鍵字。

//1. 通過閉包獲取當(dāng)前函數(shù)環(huán)境外的變量值副本。
function getMoney() {
    $rmb = 1;
    $dollar = 6;
    $func = function() use ( $rmb ) {
        echo $rmb; //1
        echo $dollar; //報錯,找不到dorllar變量
    };
    $func();
}
getMoney();

//2. 之所以稱為副本,是因?yàn)橥ㄟ^閉包傳值到匿名函數(shù)內(nèi)的變量,值也是不能改變。
function getMoney() {
    $rmb = 1;
    $func = function() use ( $rmb ) {
        $rmb += 2;
        echo $rmb; // 3
    };
    $func();
    echo $rmb; // 還是1沒有改變;
}
getMoney();

//3. 如果要改變外部變量的值,還是得通過傳址的方法
function getMoney() {
    $rmb = 1;
    $func = function() use ( &$rmb ) {
        $rmb += 2;
        echo $rmb; // 3
    };
    $func();
    echo $rmb; // 3;
}
getMoney();

//4. 
function getMoneyFunc() {
    $rmb = 1;
    $func = function() use(&$rmb){
        echo $rmb;
        //把$rmb的值加1
        $rmb++;
    };
    return $func; // 如果將匿名函數(shù)返回給外界,匿名函數(shù)會保存use所引用的變量,而外界則不能得到這些變量,這樣形成‘閉包’
}

$getMoney = getMoneyFunc();
$getMoney(); // 1
$getMoney(); // 2
$getMoney(); // 3
閉包的好處

1. 減少循環(huán)

// 一個基本的購物車,包括一些已經(jīng)添加的商品和每種商品的數(shù)量。
// 其中有一個方法用來計算購物車中所有商品的總價格。該方法使用了一個closure作為回調(diào)函數(shù)。
class Cart{
    const PRICE_BUTTER = 1.00;
    const PRICE_MILK   = 3.00;
    const PRICE_EGGS   = 6.95;

    protected $products = array();

    public function add($product , $quantity)
    {
        $this->products[$product] = $quantity;
    }

    public function getQuantity($product)
    {
        return isset($this->products[$product]) ? $this->products[$product] : false;
    }

    public function getTotal($tax)
    {
        $total = 0.00;
        // 使用閉包減少循環(huán);
        $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);;
    }
}

$my_cart = new Cart;
// 往購物車?yán)锾砑訔l目
$my_cart->add("butter" , 1);
$my_cart->add("milk" , 3);
$my_cart->add("eggs" , 6);
// 打出出總價格,其中有 5% 的銷售稅.
print $my_cart->getTotal(0.05) . "
";
// The result is 54.29

2. 減少函數(shù)的參數(shù)

function html($code , $id = "" , $class = "")
{
    if ($id !== "")
        $id = " id = "{$id}"";
    $class = ($class !== "") ? " class ="$class"" : "";
    $open = "<$code$id$class>";
    $close = "";
    return function($inner = "") use ($open , $close){
        return "$open$inner$close";
    };
}
$tag = html("div","","class");

// 可讀性和可維護(hù)性大大提高;
echo $tag("div1,div1,div1");
echo PHP_EOL;
echo $tag("div2,div2,div2");

3. 解除遞歸函數(shù)

// ↓↓ 注意,這里的fib一定要用引用哦,因?yàn)榈谝淮蔚臅r候就會Notice: Undefined variable,然后后面的fib()就會錯誤;
$fib = function($n) use (&$fib){
    if ($n == 0 || $n == 1)
        return 1;
    return $fib($n - 1) + $fib($n - 2);
};
echo $fib(2) . "
"; // 2
$lie = $fib;
$fib = function(){
    die("error");
};//rewrite $fib variable

echo $lie(5); // error  達(dá)到遞歸解除;

4. 關(guān)于延遲綁定

$result = 0;
$one = function(){
    var_dump($result);
};
$two = function() use ($result){
    var_dump($result);
};

// 在回調(diào)生成的時候進(jìn)行賦值;
$four = function() use ($result){
    //0 回調(diào)生成的時候賦值,也就是$result = 0;
    var_dump($result);
};

// 如果使用引用,就能使use里面的變量完成延遲綁定,也就是在調(diào)用的時候再賦值;
$three = function() use (&$result){
    //1 在調(diào)用的時候再賦值進(jìn)去,也就是1,注意對象類型也屬于引用;
    var_dump($result);
};

$result += 1;

$one();    // outputs NULL: $result is not in scope
$two();    // outputs int(0): $result was copied
$three();    // outputs int(1)
$four(); // outputs int(0)
幾個配合回調(diào)或閉包的函數(shù)

bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] )

/**
 * @param array $array
 * @param callable $funcname ()
 * @param mixed|NULL $userdata
 * @return bool
 * bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] )
 */
$fruits = array(
    "d" => "lemon" ,
    "a" => "orange" ,
    "b" => "banana" ,
    "c" => "apple"
);
$test_print = function(&$item2 , $key, $prefix){
    $item2 .= " 10";
    echo "{$prefix} : $key => $item2
";
};
/*
    this result : d => lemon
    this result : a => orange
    this result : b => banana
    this result : c => apple
 */
array_walk($fruits , $test_print, "this result");

print_r($fruits);
/*
    Array
    (
        [d] => lemon 10
        [a] => orange 10
        [b] => banana 10
        [c] => apple 10
    )
 */

bool array_walk_recursive ( array &$input , callable $funcname [, mixed $userdata = NULL ]

$sweet = array(
    "a" => "apple" ,
    "b" => "banana"
);
$fruits = array(
    "sweet" => $sweet ,
    "sour" => "lemon"
);
$test_print = function($item , $key)
{
    echo "$key holds $item
";
};

array_walk_recursive($fruits , $test_print);
/*
 * 自動跳過sweet,因?yàn)閟weet是數(shù)組;任何其值為 array 的鍵都不會被傳遞到回調(diào)函數(shù)中去
    a holds apple
    b holds banana
    sour holds lemon
 */

array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

$odd = function($var){
    return ($var & 1);
};
$even = function($var){
    return (!($var & 1));
};
$array1 = array( "a" => 1 , "b" => 2 , "c" => 3 , "d" => 4 , "e" => 5 );
$array2 = array( 6 , 7 , 8 , 9 , 10 , 11 , 12 );
echo "Odd :
";
print_r(array_filter($array1 , "odd"));
/*
Odd :
Array
(
    [a] => 1
    [c] => 3
    [e] => 5
)
 */
echo "Even:
";
print_r(array_filter($array2 , "even"));
/*
Even:
Array
(
    [0] => 6
    [2] => 8
    [4] => 10
    [6] => 12
)
 */
 
 # 如果不傳第二參數(shù)的的話
 $entry = array(
    0 => "foo",
    1 => false,
    2 => -1,
    3 => null,
    4 => ""
);
print_r(array_filter($entry));
/*
 * 當(dāng)前值為false的話就filter;
Array
(
    [0] => foo
    [2] => -1
)
 */

array array_map ( callable $callback , array $arr1 [, array $array ] )

/**
 * @param callable $callback
 * @param array $arr1
 * @param array $array
 */

$func = function($value) {
    return $value * 2;
};

print_r(array_map($func, range(1, 5)));

/*
Array
(
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)
 */
 
 $show_Spanish = function($n , $m){
    return ("The number $n is called $m in Spanish");
};
$a = array( 1 , 2 , 3 , 4 , 5 );
$b = array( "uno" , "dos" , "tres" , "cuatro" , "cinco" );
$c = array_map($show_Spanish , $a , $b);
/**
print_r($c);
Array
(
[0] => The number 1 is called uno in Spanish
[1] => The number 2 is called dos in Spanish
[2] => The number 3 is called tres in Spanish
[3] => The number 4 is called cuatro in Spanish
[4] => The number 5 is called cinco in Spanish
)
 */

$map_Spanish = function($n , $m){
    return (array($n => $m));
};
$d = array_map($map_Spanish , $a , $b);
print_r($d);
/**
    Array (
    [0] => Array ( [1] => uno )
    [1] => Array ( [2] => dos )
    [2] => Array ( [3] => tres )
    [3] => Array ( [4] => cuatro )
    [4] => Array ( [5] => cinco )
    )
 */

mixed array_reduce ( array $input , callable $function [, mixed $initial = NULL ] )

/**
 * 用回調(diào)函數(shù)迭代地將數(shù)組簡化為單一的結(jié)果值,解釋不清楚的一看代碼就明白了;
 * @param array $input
 * @param callable $function
 * @param mixed|NULL $initial 如果指定了可選參數(shù) initial,該參數(shù)將被當(dāng)成是數(shù)組中的第一個值來處理,或者如果數(shù)組為空的話就作為最終返回值。
 */

$rsum = function($result , $value){
    // $result 初始值為NULL, 如果有第三參數(shù)的話,第三參數(shù)為初始值;
    $result += $value;
    return $result;
};

$rmul = function($result , $value){
    $result *= $value;
    return $result;
};

$a = array(1, 2, 3, 4, 5);
$x = array();
$b = array_reduce($a, $rsum); // (NULL)0+1+2+3+4+5 = 15;
$c = array_reduce($a, $rmul, 10); // 10*1*2*3*4*5 = 1200;
$d = array_reduce($x, $rsum, "No data to reduce"); // No data to reduce

mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )

/**
 * @param mixed $pattern 正則模式;
 * @param callable $callback
 * @param mixed $subject
 * @param int $limit 對于每個模式用于每個 subject 字符串的最大可替換次數(shù)。 默認(rèn)是-1(無限制)。
 * @param int $count 如果指定,這個變量將被填充為替換執(zhí)行的次數(shù)。
 * mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )
 */
// 將文本中的年份增加一年.
$text = "April fools day is 04/01/2002
";
$text .= "Last christmas was 12/24/2001
";

// 回調(diào)函數(shù)
$next_year = function($matches){
    // 通常: $matches[0]是完成的匹配
    // $matches[1]是第一個捕獲子組的匹配
    // 以此類推
    return $matches[1] . ($matches[2] + 1);
};

echo preg_replace_callback("|(d{2}/d{2}/)(d{4})|" , $next_year , $text);

mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )

mixed call_user_func_array ( callable $callback , array $param_arr )

/**
 * @param callable $callback 第一個參數(shù)為需要調(diào)用的函數(shù); 如果是數(shù)組array($classname, $methodname)
 * @param mixed $parameter 第二個參數(shù)開始就是隊(duì)列進(jìn)該函數(shù)的參數(shù);
 * @param mixed $parameter2
 * @param mixed $parameter3
 * ..
 * @return 返回值:返回調(diào)用函數(shù)的結(jié)果,或FALSE
 */
$eat = function($fruit , $num){ //參數(shù)可以為多個
    echo "You want to eat $fruit $num pcs, no problem
";
};
call_user_func($eat , "apple" , 10); //print: You want to eat apple 10 pcs, no problem;
call_user_func($eat , "orange" , 5); //print: You want to eat orange 5 pcs,no problem;

// 調(diào)用類方法
class myclass {
    public static function say_hello($name,$message)
    {
        echo "Hello! $name $message";
    }
}

//array(類名,靜態(tài)方法名),參數(shù)
call_user_func(array("myclass", "say_hello"), "dain_sun", "good person");

call_user_func_array(array("myclass", "say_hello"), array("dain_sun", "good person"));

// Hello! dain_sun good person

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/31417.html

相關(guān)文章

  • modernPHP專題(9)】匿名

    摘要:復(fù)制當(dāng)前閉包對象,綁定指定的對象和類作用域。類作用域,可以是對象,也可以是實(shí)例名稱什么是匿名類先理解以下三個例子例閉包函數(shù)都是繼承類返回匿名函數(shù)返回匿名函數(shù),也就是閉包函數(shù),所有閉包函數(shù)都是繼承類輸出例將一個匿名函數(shù)綁定到一個類中。 類結(jié)構(gòu) Closure { /* 方法 */ // 用于禁止實(shí)例化的構(gòu)造函數(shù) __construct ( void ) ...

    ninefive 評論0 收藏0
  • modernPHP專題(1)】php7常用特性整理

    摘要:它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時拋出特定異常的能力。錯誤和異常改變了大多數(shù)錯誤的報告方式。不同于傳統(tǒng)的錯誤報告機(jī)制,現(xiàn)在大多數(shù)錯誤被作為異常拋出。 PHP7性能 7最大的亮點(diǎn),應(yīng)該就是性能提高了兩倍,某些測試環(huán)境下甚至提高到三到五倍,具體可以了解以下鏈接: PHP7 VS HHVM (WordPress) HHVM vs PHP 7 – The Competit...

    Render 評論0 收藏0
  • modernPHP專題(7)】生成器語法

    摘要:通過生成器來生成關(guān)聯(lián)數(shù)組下面每一行是用分號分割的字段組合,第一個字段將被用作鍵名。正常來說,產(chǎn)生的是一個,它的成員變量與函數(shù)不存在別名引用關(guān)系。關(guān)鍵字在的版本,生成器允許從其他生成器,可迭代對象或數(shù)組通過關(guān)鍵字來生成對應(yīng)的值輸出 一般你在迭代一組數(shù)據(jù)的時候,需要創(chuàng)建一個數(shù)據(jù),假設(shè)數(shù)組很大,則會消耗很大性能,甚至造成內(nèi)存不足。 //Fatal error: Allowed memory ...

    jackwang 評論0 收藏0
  • modernPHP專題(3)】依賴注入與服務(wù)容器

    摘要:而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。上面通過構(gòu)造函數(shù)注入對象的方式,就是最簡單的依賴注入當(dāng)然注入不僅可以通過構(gòu)造函數(shù)注入,也可以通過屬性注入,上面你可以通過一個來動態(tài)為這個屬性賦值。 依賴倒置和控制反轉(zhuǎn)是一種編程思想,而依賴注入就是通過服務(wù)容器實(shí)現(xiàn)這種面向接口或者是面向抽象編程的思想 概念理解 依賴倒置原則 依賴倒置是一種軟件設(shè)計思想,在傳統(tǒng)軟件中,上層代碼依賴于下...

    terro 評論0 收藏0
  • modernPHP專題(11)】斷言ASSERT

    摘要:可以在任何時候啟用和禁用斷言驗(yàn)證,因此可以在測試時啟用斷言,而在部署時禁用斷言。會檢查指定的并在結(jié)果為時采取適當(dāng)?shù)男袆右暥?。中的斷言向后兼用并增?qiáng)之前的的方法。它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時拋出特定異常的能力。 簡述 編寫代碼時,我們總是會做出一些假設(shè),斷言就是用于在代碼中捕捉這些假設(shè),可以將斷言看作是異常處理的一種高級形式。程序員斷言在程序中的某個特定點(diǎn)該...

    WalkerXu 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<