箭头函数

箭头函数是 PHP 7.4 的新语法,是一种更简洁的 匿名函数 写法。

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

箭头函数的基本语法为 fn (argument_list) => expr

箭头函数支持与 匿名函数 相同的功能,只是其父作用域的变量总是自动的。

当表达式中使用的变量是在父作用域中定义的,它将被隐式地按值捕获。在下面的例子中,函数 $fn1$fn2 的行为是一样的。

Example #1 箭头函数自动捕捉变量的值

<?php

$y 
1;

$fn1 fn($x) => $x $y;
// 相当于 using $y by value:
$fn2 = function ($x) use ($y) {
    return 
$x $y;
};

var_export($fn1(3));
?>

以上例程会输出:

4

在箭头函数嵌套的情况下同样有效。

Example #2 箭头函数自动捕捉变量的值,即使在嵌套的情况下

<?php

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

和匿名函数一样,箭头函数语法同样允许标准的函数声明,包括参数和返回类型、缺省值、变量,以及通过引用传递和返回。以下都是箭头函数的有效例子。

Example #3 合法的箭头函数例子

<?php

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

?>

箭头函数会自动绑定上下文变量,这相当于对箭头函数内部使用的每一个变量 $x 执行了一个 use($x)。这意味着不可能修改外部作用域的任何值,若要实现对值的修改,可以使用 匿名函数 来替代。

Example #4 来自外部范围的值不能在箭头函数内修改

<?php

$x 
1;
$fn fn() => $x++; // 不会影响 x 的值
$fn();
var_export($x);  // 输出 1

?>

更新日志

版本 说明
7.4.0 新增箭头函数语法。

注释

Note: 可以对箭头函数使用 func_num_args(), func_get_arg(), 和 func_get_args() 函数。

User Contributed Notes

itsunclexo at gmail dot com 04-Apr-2021 10:13
As you already know, variable bindings occur in arrow functions by "by-value".  That means, an arrow function returns a copy of the value of the variable used in it from the outer scope.

Now let us see an example of how a arrow function returns a reference instead of a copy of a value.

<?php

$x
= 0;

$fn = fn &(&$x) => $x// Returns a reference

$y = &$fn($x);  // Now $y represents the reference

var_dump($y);  // Outputs: 0

$y = 3// Changing value of $y affects $x

var_dump($x);  // Ouputs: 3

?>
InvisibleSmiley 12-Jan-2021 08:07
Unlike anonymous functions, arrow functions cannot have a void return type declaration.

May seem obvious, but if you thought you could make use of the benefits of arrow functions (using variables from the parent scope) to simplify a function or method call, keep in mind that this is only possible if you do NOT tell PHP that the arrow function does indeed return void.
zhangchengming at kkguan dot com 14-Dec-2020 08:00
<?php

$x
= 1;

(
fn() => print($x))(); // Outputs 1

(fn($x) => print($x))(2); // Outputs 2
dexen dot devries at gmail dot com 03-Aug-2020 07:39
Beware compact() not being able to access (import) variables from external scope (known in versions: 7.4.0, 7.4.8) (bug: https://bugs.php.net/bug.php?id=78970).

A workaround is available - use the variable directly; this will cause it to be imported into the arrow function's namespace and make it available to the compact() too.

<?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));
?>

result:
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)
}
Koushil Mankali 27-Jul-2020 06:58
In example 4  (Values from the outer scope cannot be modified by arrow functions)

<?php

$x
= 1;
$fn = fn() => $x++; // Has no effect
$fn();
var_export($x);  // Outputs 1

?>

Here we can use reference variable in fn(&$x) and pass the value from function call $fn($x) so that we will get the output as expected with out using Anonymous functions.

Example:

<?php

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

?>

Output : 2 (as expected)

But here it will not take values from parent scope automatically but we have to pass them explicitly.