Menu

PHP 箭头函数:fn() => 语法和示例

箭头函数是只含一个表达式的匿名函数,写作 fn($x) => $x * 2。它会自动按值使用外部变量,不需要 use。本文讲解它的语法、变量捕获的方式、类型声明、作为 array_map 和 usort 的回调,以及什么时候应该改用完整的闭包。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

箭头函数是一种简短的匿名函数:fn($x) => $x * 2。=> 后面的函数体是一个表达式,它的值就是返回值;表达式用到的外部变量会被自动按值捕获。箭头函数从 PHP 7.4 开始提供,最常用来写回调。

语法

fn、参数列表、=>,再加一个表达式。参数类型、默认值和返回类型的写法和普通函数完全一样:

箭头函数没有 return 关键字,也没有花括号。为了好读,很长的表达式仍然可以拆成几行。

外部变量按值捕获

箭头函数能看到创建它时所在作用域里的每个变量,并在那一刻复制它们的值。在函数里做的修改只留在函数里,函数创建之后在外面做的修改它也看不到:

这就是它和 function () use (&$count) 的主要区别:后者可以按引用共享一个变量,箭头函数则不能给外部变量重新赋值。不过它仍然可以修改捕获到的对象(副本是指向同一个对象的句柄),而按引用声明的参数也和普通函数一样有效:fn(array &$list) => $list[] = 'x'。

作为 array_map、array_filter 和 usort 的回调

大多数数组函数都接收回调,箭头函数在这里最能减少冗余代码。对比一下同一个过滤操作的两种写法:

<=> 返回 -1、0 或 1,正好是 usort() 需要的值,所以按某个字段排序只要一行。把 $a 和 $b 对调就能降序排序。

返回箭头函数的箭头函数

被捕获的变量也包括外层箭头函数的参数,所以你可以把箭头函数嵌套起来,用一些值生成新的函数:

注意 array_filter() 会保留原来的键,所以结果从索引 1 开始。

fn 与 function:什么时候需要完整的闭包

当函数体需要不止一个表达式,或者必须修改外部变量时,箭头函数就不够用了。这时请使用匿名函数:

fn($x) => ...function ($x) use ($y) { ... }
函数体一个表达式任意语句
返回自动返回显式 return
外部变量用到的全部自动捕获只有 use 中列出的
按引用捕获不支持支持,use (&$y)
起始版本PHP 7.4PHP 5.3

如果一个箭头函数写起来很憋屈,往往说明这件事其实是两件事。像上面那样把它拆成一次过滤和一次求和,每个回调就又能保持为一个表达式。

常见问题

PHP 箭头函数是什么?

PHP 7.4 引入的简短匿名函数:fn($x) => $x * 2。它的函数体只有一个表达式,表达式的值会自动返回,并且不需要 use 子句就能读取外层作用域的变量。

PHP 箭头函数可以写多行吗?

不可以。=> 后面的函数体必须是一个表达式,不能是包含多条语句的代码块。你可以把很长的表达式拆成几行来写,但如果需要 if、循环或多条语句,就改用 function () use (...) { ... }。

箭头函数能修改外部变量吗?

不能。箭头函数按值捕获外部变量,所以 fn() => $count++ 只会改动它自己的副本,外面的 $count 保持不变。要修改外部变量,请使用带 use (&$count) 的闭包。

PHP 中 fn 和 function 有什么区别?

fn($x) => ... 只包含一个表达式,隐式返回它的值,并按值捕获用到的所有外部变量。function ($x) use ($y) { ... } 可以包含任意语句,需要显式 return,而且只能看到 use 中列出的变量,这些变量可以按引用捕获。

Coddy 编程语言插图

和 Coddy 一起学编程

开始