PHP 閉包

接觸PHP一段時間以來,我一直以爲這是一種基於函數式編程的語言是沒有閉包這種東西的,但事實上卻顛覆了我的想法,PHP竟然有閉包,下面我們一起來接觸一下PHP的所謂的閉包。

 

根據PHP官網的定義來看,閉包(closure)又可以叫做匿名函數(Anonymous function),其實我們知道在JS中,閉包和匿名函數有着一定的區別,但是在PHP中卻等同了,那麼這肯定有一些區別的,那麼我們和JS當中的閉包對比的來看看。

 

1、語句結構

在JS中,閉包和普通的函數定義沒有什麼區別,但是在PHP中,由於存在函數內部不能訪問全局作用的,所以就需要一種可以引入上一級作用域的語法結構,這種就是

function () use () {}

將需要引入到這個函數作用於內的變量寫入到use的括號裏面就可以了,舉個例子

複製代碼

<?php

$a = 1;

$closure = function () use ($a) {
    echo $a;
};

$closure();

?>

複製代碼

輸出的結果爲

1

這次就實現了閉包的功能了,可以和上級作用域產生了聯繫了

 

2、變量執行的時候是運行時賦值還是函數聲明的時候賦的值?

學過JS的到這裏一定認爲這個$a變量當變化的時候,根據JS引用的理論,函數執行的結果也是變化的,但事實究竟是這樣麼?看例子:

複製代碼

<?php

$a = 1;

$closure = function () use ($a) {
    echo $a;
};

$closure();

$a=2;

$closure();

?>

複製代碼

大家猜猜結果會是什麼?

1 1

哎??爲什麼不是 1 2 呢?

因爲對於PHP來說的閉包當聲明閉包的時候,就已經將值重新開闢了一塊內存賦值給了use中的a所以,不過外部的 a所以,不過外部的 a怎麼變,閉包執行的結果是不變的,那麼我們怎麼能讓他變化呢?

 

先給大家一個提示,PHP實現閉包的本質其實是將這個特殊的函數轉換成了一個類。

 

說到這裏,大家是不是有一點明白了呢?既然是類,那麼我們可以使用引用來傳遞use當中的值。

讓我們再試一下

複製代碼

<?php

$a = 1;

$closure = function () use (&$a) {//注意這裏,加了一個&
    echo $a;
};

$closure();

$a=2;

$closure();

?>

複製代碼

再運行一下看看

1 2

這次結果對了吧。

 

不僅如此,引用之後,如果在閉包當中修改引入的變量值,原本的變量的值也會修改的,但是不過不加&,那麼在閉包中修改變量的值得時候,即使這次修改有效了,下次重新運行閉包函數後又會回到之前的值,相當於沒有修改。舉個例子:

不加&:

複製代碼

<?php
$a = 1;
$closure = function () use ($a) {
    $a++;
    echo $a,' ';
};
$closure();
$closure();
$a=-5;
$closure();
$closure();
?>

複製代碼

輸出爲:

2 2 2 2

加了&之後

輸出爲

2 3 -4 -3

 

 

總結:

對應PHP中的閉包,和JS中的閉包還是有本質的區別的,JS的閉包是語言原生支持的,所以感覺比較符合人的思考方式,而PHP得閉包就是將閉包的這種特性抽象成了類的方式,然後以類的形式進行處理,畢竟是抽象出來的,還不是很符合人們的思考方式。

 

在接觸了PHP的閉包之後,我深深的覺得PHP真是雜啊………………

 

PS:

1、不要忘記了在閉包的賦值語句最後面的分號,畢竟這是一個語句,還要是有分號的。

2、對於函數的傳入參數等東西,和普通的參數寫法是一樣的。

3、要注意函數調用的時候不要忘記了,因爲閉包函數的本質還是一個變量的,不過是一個可以執行的變量了而已。如果去掉 ,因爲閉包函數的本質還是一個變量的,不過是一個可以執行的變量了而已。如果去掉 ,PHP解釋器將會認爲這是一個函數而不是一個閉包函數從而出錯。

4、除了上面的那幾點和JS的不同以外,其他的都是可以的,比如可以作爲函數的返回值等等的內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章