在PHP中如何爲匿名函數指定this?
在以前的文章中,咱們已經學習過匿名函數的使用,沒有看過的小夥伴能夠進入傳送門先去了解下閉包匿名函數的用法,傳送:還不知道PHP有閉包?那你真OUT了。php
關於閉包匿名函數,在JS中有個很典型的問題就是要給它綁定一個 this 做用域。其實這個問題在PHP中也是存在的,好比下面這段代碼:git
$func = function($say){
echo $this->name, ':', $say, PHP_EOL;
};
$func('good'); // Fatal error: Uncaught Error: Using $this when not in object context
在這個匿名函數中,咱們使用了 \$this->name 來獲取當前做用域下的 $name 屬性,但是,這個 $this 是誰呢?咱們並無定義它,因此這裏會直接報錯。錯誤信息是:使用了 $this 可是沒有對象上下文,也就是說沒有指定 $this 引用的做用域。github
bindTo() 方法綁定 $this
好吧,那麼咱們就給它一個做用域,和 JS 同樣,使用一個 bindTo() 方法便可。web
$func1 = $func->bindTo($lily, 'Lily');
// $func1 = $func->bindTo($lily, Lily::class);
// $func1 = $func->bindTo($lily, $lily);
$func1('cool');
這回就能夠正常輸出了。bindTo() 方法是複製一個當前的閉包對象,而後給它綁定 $this 做用域和類做用域。其中, $lily 參數是一個 object $newthis 參數,也就是給這個複製出來的匿名函數指定 $this 。而第二個參數 'Lily' 則是綁定一個新的 類做用域 ,它表明一個類型、決定在這個匿名函數中可以調用哪些 私有 和 受保護 的方法,上例中給出的三種方式均可以用來定義這個參數。若是不給這個參數,那麼咱們就不能訪問這個 private 的 $name 屬性了:微信
$func2 = $func->bindTo($lily);
$func2('cool2'); // Fatal error: Uncaught Error: Cannot access private property Lily::$name
call() 方法綁定 $this
在PHP7之後,PHP新增長了 call() 方法來進行匿名函數的 $this 綁定,咱們來看看它和 bindTo() 方法有哪些區別。閉包
$func->call($lily, 'well'); // Lily:well
額......編輯器
是否是感受方便好多。首先,它直接執行了,不須要再賦值給一個變量,也就是說,它不是去複製那個閉包函數的而是直接執行了;其次,沒有 類做用域 這個概念了,第一個參數仍是指定新的 $this 的指向,然後面的參數就是原來閉包函數的參數。函數
雖然很方便,可是它也帶來了另外一個問題,由於沒有 類做用域 的限制,因此會破壞封裝。你好不容易作好的面向對象的設計,封裝了一堆屬性,而後使用這個 call() 就讓對象的全部 私有 和 受保護 內容都暴露了出來。固然,這也是看咱們本身的業務狀況了,畢竟兩種形式咱們在寫代碼的時候都是能夠自由選擇的。學習
總結
其實包括閉包函數在內,這些特性都很是像JS。這也是語言融合的一種趨勢,不論是學習了JS來看PHP的這些特性仍是先學了PHP再去看JS,都會讓咱們更容易理解它們的做用與能力,這就是語言特性融合帶來的好處。無論怎麼樣,學就是了,繼續加油吧!!測試
測試代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202002/source/%E5%9C%A8PHP%E4%B8%AD%E5%A6%82%E4%BD%95%E4%B8%BA%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%E6%8C%87%E5%AE%9Athis%EF%BC%9F.php
參考文檔:
https://www.php.net/manual/zh/functions.anonymous.php
https://www.php.net/manual/zh/closure.bindto.php
https://www.php.net/manual/en/closure.call.php
本文分享自微信公衆號 - 硬核項目經理(fullstackpm)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。