PHP 8.4.2 Released!

箭头函数

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

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

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

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

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

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

<?php

$y
= 1;

$fn1 = fn($x) => $x + $y;
// 相当于通过 value 使用 $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++; // 不会影响 x 的值
$fn();
var_export($x); // 输出 1

?>

更新日志

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

注释

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

添加备注

用户贡献的备注 5 notes

up
40
InvisibleSmiley
3 years ago
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.
up
42
Koushil Mankali
4 years ago
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.
up
23
itsunclexo at gmail dot com
3 years ago
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

?>
up
15
dexen dot devries at gmail dot com
4 years ago
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)
}
up
1
aaronw at catalyst dot net dot nz
16 days ago
If you're a JavaScript developer, here are the similarities and differences to JS arrow functions:

Same:
- Makes an anonymous function
- Binds the value of "$this" to its value in the parent scope.
- (along with all other variables of the parent scope. See note below)

Different:
- You must write "fn()" instead of just "()"
- The function body is limited to just ONE expression
- So no multi-line function bodies with "{" and "}"

Same and Different at the same time:
- Binds ALL the variables of the parent scope
- In JavaScript all functions are closures, binding to the variables in their parent scope (except for "this").
- But in PHP, normal anonymous functions (defined with "function() {}") do NOT get access to the parent scope, unless they explicitly declare a closure with keyword "use"
- PHP arrow functions, on the other hand, automatically bind to ALL variables in the parent scope. So, this makes them behave the same as JS functions, but be aware that in PHP this is special behavior unique to arrow functions.
To Top