在 PHP 中,以往我們傳遞閉包函式引數的時候,往往需要寫很多重複性的程式碼。在 PHP 7.4 中,我們在閉包裡面如果只是返回一個簡單的表示式的時候,我們可以以一種更簡潔的方式來傳遞閉包引數了。
以往寫法
在以往的 PHP 版本中,我們使用匿名函式的方式可能會顯得非常冗長,即使裡面只是一個簡單的返回,或者一個簡單的表示式。
比如:
$students = [
[
'name' => 'Foo',
'age' => 20,
],
[
'name' => 'Bar',
'age' => 21,
],
];
$names = array_map(function ($student) {
return $student['name'];
}, $students);
寫過 ES6 或者 Java8 的朋友應該對箭頭函式這種寫法比較熟悉,對比一下:
ES6
let names = students.map(student => student.name)
JAVA8 則類似下面的 map 那樣
students.stream()
.map(student -> student.name)
.collect(Collectors.toList())
相對比之下,php 就顯得有些囉嗦,如果閉包函式里面需要使用外部變數,則還需要把每一個外部變數寫到 use 裡面,那就會更加冗長。
箭頭函式 hello world
現在我們使用箭頭函式來重寫一下上面的 array_map
呼叫:
$names = array_map(fn ($student) => $student['name'], $students);
var_dump($names);
線上執行以上程式碼: php74-playground
怎麼樣?是不是簡潔又清晰,看起來特別舒服。 function
、return
、use
這些全都不用寫了。
同時,如果需要使用外部的變數,再也不需要使用 use 來引入那些外部變數了,在箭頭函式後面的表示式直接可以使用:
$y = 10;
$fn = fn ($x) => $x + $y;
var_dump($fn(20)); // 30
線上執行以上程式碼: php74-playground
舊的寫法:
$y = 10;
$fn = function ($x) use ($y) {
return $x + $y;
};
var_dump($fn(20)); // 30
箭頭函式寫法
基本形式
fn (parameter_list) => expr
簡單說一下(但是很重要):
fn
是箭頭函式標識,原來的function
關鍵字在箭頭函式里只需寫fn
(parameter_list)
是箭頭函式的引數列表,fn
和 括號不能省略expr
這個名字已經說明了一切,這裡我們只能寫一個表示式,不能寫多個語句,不接受語句塊。expr
是一個表示式,同時也是這個箭頭函式的返回值,原來的return
不用寫了
有人會說,為什麼還要寫 fn
,直接 parameter => expr
不就好了嗎?
這是因為這種寫法已經用於 PHP 的關聯陣列裡面了,衝突了。
想了解為什麼的可以看 rfc/arrow_functions_v2。
函式簽名
fn (array $x) => $x;
,引數型別限定fn (): int => $x;
,返回值型別限定fn ($x = 42) => $x;
,引數預設值fn (&$x) => $x;
,引數引用傳遞fn &($x) => $x;
,返回值引用fn ($x, ...$rest) => $rest;
總的來說:
引數傳遞、引數型別限定、返回值型別限定、引用引數傳遞、返回值引用等寫法和舊的寫法一致。
不一樣的是:
-
沒有了
function
、return
、use
等關鍵字,也沒有了大括號 -
需要注意的是:不支援大括號,不像 ES6
- 錯誤寫法:
fn (array $x) => {return $x;};
- 錯誤寫法:
相容性問題
- 從 PHP 7.4 起,因為引入了 fn 關鍵字作為箭頭函式的語法,因此,如果你的程式碼裡面有 fn 命名的函式,可能會有衝突。
總結
-
基本語法
fn (parameter_list) => expr
-
PHP7.4 的箭頭函式只支援簡單的表示式(只能寫一個表示式),不能使用大括號把表示式括起來
想嚐鮮的可以在 php74-playground 嘗試一下!基於 PHP 7.4.0RC1
版本。
本作品採用《CC 協議》,轉載必須註明作者和本文連結