PHP 日本大会 2024

箭头函数

箭头函数在 PHP 7.4 中引入,作为匿名函数的一种更简洁的语法。

匿名函数和箭头函数都是使用Closure类实现的。

箭头函数的基本形式为fn (argument_list) => expr

箭头函数支持与匿名函数相同的特性,只是始终自动使用父作用域中的变量。

当表达式中使用的变量在父作用域中定义时,它将隐式按值捕获。在下面的示例中,函数$fn1$fn2的行为方式相同。

示例 #1 箭头函数自动按值捕获变量

<?php

$y
= 1;

$fn1 = fn($x) => $x + $y;
// 等同于按值使用 $y:
$fn2 = function ($x) use ($y) {
return
$x + $y;
};

var_export($fn1(3));
?>

上面的例子将输出

4

如果箭头函数嵌套,这也适用

示例 #2 箭头函数自动按值捕获变量,即使嵌套也是如此

<?php

$z
= 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// 输出 51
var_export($fn(5)(10));
?>

与匿名函数类似,箭头函数语法允许任意函数签名,包括参数和返回类型、默认值、可变参数,以及按引用传递和返回。以下所有都是箭头函数的有效示例

示例 #3 箭头函数示例

<?php

fn(array $x) => $x;
static fn(
$x): int => $x;
fn(
$x = 42) => $x;
fn(&
$x) => $x;
fn&(
$x) => $x;
fn(
$x, ...$rest) => $rest;

?>

箭头函数使用按值变量绑定。这大致等同于对箭头函数内使用的每个变量$x执行use($x)。按值绑定意味着无法修改外部作用域中的任何值。匿名函数可用于按引用绑定。

示例 #4 箭头函数无法修改外部作用域的值

<?php

$x
= 1;
$fn = fn() => $x++; // 无效
$fn();
var_export($x); // 输出 1

?>

变更日志

版本 描述
7.4.0 箭头函数可用。

备注

注意可以在箭头函数中使用func_num_args()func_get_arg()func_get_args()

添加备注

用户贡献的备注 5 条备注

InvisibleSmiley
3 年前
与匿名函数不同,箭头函数不能有 void 返回类型声明。

这看起来可能很明显,但如果您认为可以利用箭头函数的优点(使用父作用域中的变量)来简化函数或方法调用,请记住,只有在您没有告诉 PHP 箭头函数确实返回 void 时才有可能。
Koushil Mankali
4 年前
在示例 4(箭头函数无法修改外部作用域的值)中

<?php

$x
= 1;
$fn = fn() => $x++; // 无效
$fn();
var_export($x); // 输出 1

?>

在这里,我们可以在 fn(&$x) 中使用引用变量,并从函数调用 $fn($x) 传递值,以便我们可以按预期获得输出,而无需使用匿名函数。

示例

<?php

$x
= 1;
$fn = fn(&$x) => $x++;
$fn($x);
var_export($x);

?>

输出:2(预期结果)

但是在这里,它不会自动获取父作用域中的值,我们必须显式传递它们。
itsunclexo at gmail dot com
3 年前
如您所知,变量绑定在箭头函数中按“按值”进行。这意味着,箭头函数返回在其内部使用的变量从外部作用域的值的副本。

现在让我们看一个箭头函数返回引用而不是值副本的示例。

<?php

$x
= 0;

$fn = fn &(&$x) => $x; // 返回一个引用

$y = &$fn($x); // 现在 $y 代表该引用

var_dump($y); // 输出:0

$y = 3; // 更改 $y 的值会影响 $x

var_dump($x); // 输出:3

?>
dexen dot devries at gmail dot com
4 年前
注意 `compact()` 函数无法访问外部作用域的变量 (已知版本:7.4.0, 7.4.8) (bug: https://bugs.php.net/bug.php?id=78970).

有一个解决方法 - 直接使用变量;这将使其导入到箭头函数的命名空间中,并使其也对 `compact()` 可用。

<?php
$aa
= 111;
$accessing_variable_works = fn($bb) => [ $aa, $bb ];
$compact_is_broken = fn($bb) => compact('aa', 'bb');
$compact_can_work_with_workaround = fn($bb) => compact('aa', 'bb') + ['workaround' => $aa];
var_dump($accessing_variable_works(333));
var_dump($compact_is_broken(555));
var_dump($compact_can_work_with_workaround(777));
?>

结果
array(2) {
[0]=>
int(111)
[1]=>
int(333)
}
PHP Notice: compact(): Undefined variable: aa in /home/m/vlt/guitar/tlb/s/public_html/index.php on line 9
array(1) {
["bb"]=>
int(555)
}
array(3) {
["aa"]=>
int(111)
["bb"]=>
int(777)
["workaround"]=>
int(111)
}
aaronw at catalyst dot net dot nz
12小时前
如果您是 JavaScript 开发人员,以下是与 JS 箭头函数的异同

相同点
- 创建一个匿名函数
- 将 “$this” 的值绑定到父作用域中的值。
- (以及父作用域的所有其他变量。请参见下面的注释)

不同点
- 你必须写 “fn()” 而不仅仅是 “()”
- 函数体仅限于一个表达式
- 所以没有使用 “{” 和 “}” 的多行函数体

相同点和不同点
- 绑定父作用域中的所有变量
- 在 JavaScript 中,所有函数都是闭包,绑定到其父作用域中的变量(除了 “this”)。
- 但在 PHP 中,普通匿名函数(用 “function() {}” 定义)无法访问父作用域,除非它们用关键字 “use” 显式声明闭包。
- 另一方面,PHP 箭头函数会自动绑定到父作用域中的所有变量。因此,这使它们的的行为与 JS 函数相同,但请注意,在 PHP 中,这是箭头函数特有的特殊行为。
To Top