提到閉包和匿名函數似乎一下子就想到了 javascript ,但其實在很多語言中都有閉包的特性。但是 javascript 坑爹的變量作用域讓閉包變得非常重要。而其他語言完善私有共有變量和繼承讓閉包似乎沒有什么卵用。但是為了有點B格,還是看了看 php 的閉包。
閉包個人理解就是可以訪問不同作用域內變量的方式。在 javascript 中,變量的作用域都是遵循從下往上的原則,而最上級的變量是掛載在 window 對象中(nodejs 是掛載在 gloub 中),這就意味著如果隨意定義的變量的話,掛載在最上級作用域的變量會越來越多,甚至會產生重名、覆蓋等問題,這就是經常提到的變量污染。所以會使用閉包來解決變量污染和跨作用域訪問變量。但是在 php 中有系統全局變量、一般的變量、常量、全局變量、靜態變量,作用域劃分明確。所以閉包在 php 中不是那么重要,所以理解起來也有點難度。(反正我是沒理解 php 閉包有什么卵用)。匿名函數則允許我們創建一個沒有指定名稱的函數,同時擁有一個執行環境。匿名函數是完成閉包的常用方式。php5.3 之后引入了匿名函數的概念,laravel、CodeIgniter、Yii等框架都或多或少的使用的匿名函數和閉包。所以我們還是有必要了解一下。
//把函數做為參數傳入functioncallFun($func){? ? ? ? $func("some string\r\n");? ? }//php寫法$fun=function($str){echo$str;? ? };//注意這里要帶上結束符號,因為此時是賦值語句callFun($fun);//js寫法callFun(function($str){echo$str;? ? });
雖然從寫法上看和 javascript 沒有什么區別,但是在使用的時候還是有一定的區別。主要表現在變量作用域方面。在 javascript 中閉包函數可以使用上級作用域的變量。
functionfun(){vara=1;returnfunction(){? ? console.log(a);? }}varcallfun=fun();callfun();//1
但是在 php 中卻不能這樣使用。
functioncallFun(){? ? ? ? $v=1;? ? ? ? $func=function(){echo$v;//Notice: Undefined variable: v};? ? ? ? $func();? ? }? ? callFun();
這樣會報一個警告,變量$v沒有定義。php 中需要使用use關鍵字來解決這個問題。
$func1=function()use($v){echo$v;//1$v++;? ? ? ? };? ? ? ? $func1();echo$v;//1
這時候和閉包函數內的$v改變不是影響到上級函數作用域內的變量。同樣的,可以使用引用來關聯。
$func2=function()use(&$v){echo$v;//1$v++;? ? ? ? };? ? ? ? $func2();echo$v;//2
閉包的使用非常廣泛,比如簡化代碼、替換遞歸、替代循環等等…這里提供一個替代遞歸的方法。
//遞歸functionfunc ($v){if($v<10){ 123456789=""echo=""$v;=""$v++;=""func($v);=""}=""101098765432=""func(1);=""閉包=""$fib="function($n)"use(&$fib)=""{=""if($n<10){=""$n;=""$fib($n+1);=""10987654321=""};=""$fib(1);=""<=""code="">
可以看到執行結果上還是有少許差異,使用過程中一定要注意。另外據說閉包的執行效率并不是很好,所以使用的時候還是要視情況而定。
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。互聯網+時代,時刻要保持學習,攜手千鋒PHP,DreamItPossible。