PHP中的閉包和匿名函數

来源:http://www.cnblogs.com/praglody/archive/2017/12/24/8098835.html
-Advertisement-
Play Games

閉包是指在創建時封裝周圍狀態的函數。即使閉包所在的環境不存在了,閉包中封裝的狀態依然存在。匿名函數就是沒有名稱的函數。匿名函數可以賦值給變數,還能像其他任何PHP對象那樣傳遞。不過匿名函數仍是函數,因此可以調用,還可以傳入參數。匿名函數特別適合作為函數或方法的回調。 ...


PHP中的閉包和匿名函數

閉包是指在創建時封裝周圍狀態的函數。即使閉包所在的環境不存在了,閉包中封裝的狀態依然存在。

匿名函數就是沒有名稱的函數。匿名函數可以賦值給變數,還能像其他任何PHP對象那樣傳遞。不過匿名函數仍是函數,因此可以調用,還可以傳入參數。匿名函數特別適合作為函數或方法的回調。

註意:理論上講,閉包和匿名函數是不同的概念。不過,PHP將其視作相同的概念。所以,我們提到閉包時,指的也是匿名函數,反之亦然。

PHP閉包和匿名函數使用的句法與普通函數相同,但閉包和匿名函數其實是偽裝成函數的對象(Closure類的實例)

創建閉包

$closure = function ($name){
    return sprintf("Hello %s", $name);
}

echo $closure("jerry");

// 檢測$closure變數是否是一個閉包
var_dump($closure instanceof Closure);

以上代碼創建了一個閉包對象,然後將其賦值給$closure變數。閉包和普通的PHP函數很像,使用的句法相同,也接收參數,而且能返回值。

說明:我們之所以能夠調用$closure變數,是因為這個變數的值是一個閉包,而且閉包對象實現了__invoke()魔術方法。只要變數名後有(),PHP就會查找並調用__invoke()方法。

使用閉包

我們通常把PHP閉包當做當做函數和方法的回調使用。很多PHP函數都會用到回調函數,例如array_map()preg_replace_callback().如下示例,我們將用array_map()處理數組,將數組每一項自增1:

$nubmers = array_map(function ($number) {
    return $number++;
}, [1,2,3]);

var_dump($numbers);

附加狀態

PHP閉包不會像真正的javascrypt閉包那樣自動封裝應用的狀態,我們必須手動調用閉包對象的bindTo()方法或者使用use關鍵字,把狀態附加到PHP閉包上。

  • 使用use關鍵字

    使用use關鍵字來附加閉包狀態更加常見,因此我們先來看這種方式。使用use關鍵字把變數附加閉包上時,附加的變數會記住附加時賦給它的值。

    function Car ($name){
        return function ($statu) use ($name){
           return sprintf("Car %s is %s", $name, $statu); 
        }
    }
    
    // 將車名封裝在閉包中
    $car = Car("bmw");
    
    // 調用車的動作
    // 輸出--> "bmw is running"
    echo $car("running");

    註意:使用use關鍵字可以把多個參數傳入閉包,此時要像PHP函數或方法的參數一樣,使用逗號分隔多個參數。

  • 使用bindTo()方法附加閉包的狀態

    與其它PHP對象類似,每個閉包實例都可以使用$this關鍵字獲取閉包的內部狀態。閉包對象的預設狀態沒什麼用,不過有一個__invoke()魔術方法和bindTo()方法。

    bindTo()方法為閉包增加了一些有趣的潛力。我們可以使用這個方法把Closure對象的內部狀態綁定到其它對象上。

    bindTo()方法的第二個參數很重要,其作用是指定綁定閉包的那個對象所屬的PHP類。因此,閉包可以訪問綁定閉包的對象中受保護和私有的成員變數。

    class TestClosure
    {
        private $name=[];
        private $age;
        private $sex;
    
        public function addPerson($name, $personCallback){
            // 將閉包對象綁定當前實例
            $this->name[$name] = $personCallback->bindTo($this, __CLASS__);
        }
    
        public function display($name){
            foreach ($this->name as $key => $callback){
                if($key == $name){
                    // 執行閉包對象,將閉包狀態附加到類
                    $callback();
                }
            }
    
            echo "name : {$name}\n";
            echo "age : {$this->age}\n";
            echo "sex : {$this->sex}\n";
        }
    
    }
    
    $person = new TestClosure();
    $person->addPerson("jerry", function(){
        $this->age = 19;
        $this->sex = "man";
    });
    $person->display("jerry");
    
    /** output
    
    name : jerry
    age : 19
    sex : man
    
    */

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • java二分查找法 今晚上在逛碼雲的時候,看到一個php的二分查找法,看著這詞比較熟悉,(因為當時學php的時候也學過,只是工作中沒用過,又加上學的時候就稀里糊塗的,慢慢的就忘了),就點進去了,就用java寫了一遍,使用的遞歸。 二分查找法的個人理解: 首先你得是個從小到大順序的數組,進行數組索引取 ...
  • 建模的重要性: 為了更好的理解一個系統 管理複雜度(也就是為了敏捷開發) 理解不同的關註點 儘早發現問題和遺漏 與項目干係人進行溝通 驅動實現 資源高效利用 ...
  • 簡單聊天Demo 使用tcp協議實現的簡單聊天功能(非常簡單的) 思想:使用2個線程,一個線程是用來接收消息的,另一個線程是用來發消息的。 客戶端Demo代碼: 伺服器端Demo代碼: 發送線程的Demo代碼: 接收線程的Demo代碼: ...
  • 今天的學習內容是python中的列表的相關內容。 一.創建列表 1.創建一個普通列表 2.創建一個混合列表 3.創建一個空列表 三種方式就介紹給大家了,接下來,如果想向列表中添加元素,該怎麼辦呢? 二.向列表中添加元素 1.append >>> tabulation1.append('紫霞')>>> ...
  • 上一篇我們講到了AI架構之一的行為樹,本篇文章和下一篇文章我們將對行為樹進行優化,在本篇文章中我們講到的是記憶體優化 問題 上一篇中我們設計的行為樹由於直接採用new進行動態記憶體分配,沒有自己進行管理。因此行為樹各節點的存儲位置會散佈在記憶體空間的各處,行為樹在不同節點中切換時會導致Cache頻繁失效。 ...
  • Centos下通過yum安裝步驟如下: 聲明:相對比那些用源碼安裝,少了配置和新建log和data目錄,這種簡單粗暴, mongodb 常用命令: mongo 導入 json 或者csv 做法 mongoimport --db table-name --collection table-name - ...
  • eclipse中使用mybatis-generator逆向代碼生成工具出現waiting for "building workspace";com.mysql.jdbc.exceptions.jdbc4.communicationsexception: communications link fa... ...
  • Java常見的同步和非同步的區別、特點、聯繫 同步:發送一個請求,等待返回,然後再發送下一個請求 非同步:發送一個請求,不等待返回,隨時可以再發送下一個請求 同步可以避免出現死鎖,讀臟數據的發生,一般共用某一資源的時候用,如果每個人都有修改許可權,同時修改一個文件,有可能使一個人讀取另一個人已經刪除的內容 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...