提出
在匿名函數出現之前,所有的函數都需要先命名才能使用
function increment($value) { return $value + 1; } array_map('increment', [1, 2, 3]);
有的時候函數可能只需要使用一次,這時候使用匿名函數會讓程式碼更簡潔直觀,同時也避免了函數在其他地方被使用
array_map(function($value){ return $value + 1; }, [1, 2, 3]);
#定義和使用
PHP 將閉包和匿名函數視為同等概念(本文統稱為匿名函數),本質上都是偽裝成函數的物件。
匿名函數的本質是對象,因此跟對像一樣可將匿名函數賦值給某一變數
$greet = function(string $name){ echo "hello {$name}"; } $greet("jack") // hello jack
所有的匿名函數都是Closure 物件的實例
$greet instanceof Closure // true
物件並沒有什麼父作用域可言,所以需要使用use 來手動宣告使用的變量,
$num = 1; $func = function() use($num){ $num = $num + 1; echo $num; } $func(); // 2 echo $num; // 还是 1
如果要讓匿名函數中的變數生效,則需要使用引用傳值
$num = 1; $func = function() use(&$num){ $num = $num + 1; echo $num; } $func(); // 2 echo $num; // 2
從PHP 5.4 開始,在類別裡面使用匿名函數時,匿名函數的$this 將自動綁定到目前類別
class Foo { public function bar() { return function() { return $this; }; } } $foo = new Foo(); $obj = $foo->bar(); // Closure() $obj(); // Foo
如果不想讓自動綁定生效,可使用靜態匿名函數
class Foo { public function bar() { return static function() { return $this; }; } } $foo = new Foo(); $obj = $foo->bar(); // Closure() $obj(); // Using $this when not in object context
匿名函數的本質
匿名函數的本質是Closure 對象,包括了以下五個方法
Closure { private __construct ( void ) public static bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure public bindTo ( object $newthis [, mixed $newscope = "static" ] ) : Closure public call ( object $newthis [, mixed $... ] ) : mixed public static fromCallable ( callable $callable ) : Closure }
__construct - 防止匿名函數被實例化
$closure = new \Closure(); // PHP Error: Instantiation of 'Closure' is not allowed
Closure::bindTo - 複製目前匿名函數對象,並綁定指定的 $this 物件和類別作用域。通俗的說,就是手動將匿名函數與指定物件綁定,利用這一點,可以為擴充物件的功能。
// 定义商品类 class Good { private $price; public function __construct(float $price) { $this->price = $price; } } // 定义一个匿名函数,计算商品的促销价 $addDiscount = function(float $discount = 0.8){ return $this->price * $discount; } $good = new Good(100); // 将匿名函数绑定到 $good 实例,同时指定作用域为 Good $count = $addDiscount->bindTo($good, Good::class); $count(); // 80 // 将匿名函数绑定到 $good 实例,但是不指定作用域,将无法访问 $good 的私有属性 $count = $addDiscount->bindTo($good); $count(); // 报错
Closure::bind - bindTo 方法的靜態版本,有兩種用法:
用法一:實作與bindTo 方法相同的效果
$count = \Closure::bind($addDiscount, $good, Good::class);
用法二:將匿名函數與類別(而非物件)綁定,記得第二個參數要設定為null
// 商品库存为 10 class Good { static $num = 10; } // 每次销售后返回当前库存 $sell = static function() { return"当前库存为". --static::$num ; }; // 将静态匿名函数绑定到 Good 类中 $sold = \Closure::bind($sell, null, Good::class); $sold(); // 当前库存为 9 $sold(); // 当前库存为 8
call - PHP 7 新增的 call 方法可以實現綁定並呼叫匿名函數,除了語法更加簡潔外,效能也更高
// call 版本 $addDiscount->call($good, 0.5); // 绑定并传入参数 0.5,结果为 50 // bindTo 版本 $count = $addDiscount->bindTo($good, Good::class, 0.5); $count(); // 50
fromCallable - 將給定的 callable 函數轉換成匿名函數
class Good { private $price; public function __construct(float $price) { $this->price = $price; } } function addDiscount(float $discount = 0.8){ return $this->price * $discount; } $closure = \Closure::fromCallable('addDiscount'); $good = new Good(100); $count = $closure->bindTo($good); $count = $closure->bindTo($good, Good::class); // 报错,不能重复绑定作用域 $count(); // 报错,无法访问私有属性
fromCallable 等價於
$reflexion = new ReflectionFunction('addDiscount'); $closure = $reflexion->getClosure();
這裡有一點需要特別注意的是,無論是fromCallable 轉化成的閉包,還是使用反射得到的閉包,在使用bindTo 時,如果第二個參數指定綁定類,會報錯
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
以上是PHP 核心特性之匿名函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

在PHP中,trait適用於需要方法復用但不適合使用繼承的情況。 1)trait允許在類中復用方法,避免多重繼承複雜性。 2)使用trait時需注意方法衝突,可通過insteadof和as關鍵字解決。 3)應避免過度使用trait,保持其單一職責,以優化性能和提高代碼可維護性。

依賴注入容器(DIC)是一種管理和提供對象依賴關係的工具,用於PHP項目中。 DIC的主要好處包括:1.解耦,使組件獨立,代碼易維護和測試;2.靈活性,易替換或修改依賴關係;3.可測試性,方便注入mock對象進行單元測試。

SplFixedArray在PHP中是一種固定大小的數組,適用於需要高性能和低內存使用量的場景。 1)它在創建時需指定大小,避免動態調整帶來的開銷。 2)基於C語言數組,直接操作內存,訪問速度快。 3)適合大規模數據處理和內存敏感環境,但需謹慎使用,因其大小固定。

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

JavaScript中處理空值可以使用NullCoalescingOperator(??)和NullCoalescingAssignmentOperator(??=)。 1.??返回第一個非null或非undefined的操作數。 2.??=將變量賦值為右操作數的值,但前提是該變量為null或undefined。這些操作符簡化了代碼邏輯,提高了可讀性和性能。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。