在PHP中如何爲匿名函數指定this?

在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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索