iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
自我挑戰組

後端新手PHP+Laravel筆記系列 第 13

[Day13]PHP 匿名函式及箭頭函式

  • 分享至 

  • xImage
  •  

PHP函數

匿名函数

匿名函數(Anonymous functions),也稱作閉包函數(closures),它允許臨時創建一個沒有指定名稱的函數。最經常用作回調函數 callable參數的值。當然,也有其它應用的情況。

1. 匿名函數範例

<?php
// 使用回調執行正則表達式搜索和替換
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);  // 將所選的變成大寫,從index: 1開始過濾掉原先"-"
}, 'hello-world');
// 输出 helloWorld
?>

閉包函數也可以作為變量的值來使用。 PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。把一個 closure 對象賦值給一個變量的方式與普通變量賦值的語法是一樣的,最後也要加上分號 ;

2. 匿名函數變量賦值示例

<?php
$sayHi = function($name)
{
    echo "Hello $name";
}; // 記得加上分號

$sayHi('joe');
$sayHi('cherry');
?>

3. 從父作用域繼承變數

閉包可以從父作用域中繼承變量。任何此類變量都應該用 use 語言結構傳遞進去。

PHP 7.1 起,不能傳入此類變量: superglobals(超全局便量)、 $this 或者和參數重名。

從 PHP 8.0.0 開始,作用域繼承的變量列表可能包含一個尾部的逗號,這個逗號將被忽略

<?php
$message = 'hello';

// 没有 "use" php會不知道這變數從哪來
$example = function () {
    var_dump($message);
};
$example();

// 繼承父作用域 $message
$example = function () use ($message) {
    var_dump($message);
};
$example();

// Inherited variable's value is from when the function
// is defined, not when called
$message = 'world';
$example();  // 不會受到改變因為已經在上面先調用了(14行)

// Reset message
$message = 'hello';

// Inherit by-reference
$example = function () use (&$message) {
    var_dump($message);
};
$example();

// The changed value in the parent scope
// is reflected inside the function call
// 父作用域更改值,影響函式回調
$message = 'world';
$example();

// Closures can also accept regular arguments
// 閉包可使用常規變數
$example = function ($arg) use ($message) {
    var_dump($arg . ' ' . $message);
};
$example("hello");
?>

// outputs
// Notice: Undefined variable: ...
// NULL
// string(5) "hello"
// string(5) "hello"
// string(5) "hello"
// string(5) "world"
// string(11) "hello world"

箭頭函數

箭頭函數是更簡潔的匿名函數,都是屬於Closure類(閉包)的實現

箭頭函數的語法為 fn (argument_list) => expr。

箭頭函數支持與 匿名函數 相同的功能,只是其父作用域的變量總是自動的。 當表達式中使用的變量是在父作用域中定義的,它將被隱式地按值捕獲。

在下面的例子中,函數 $fn1 和 $fn2 的行為是一樣的

1. 箭頭函數自動捕捉變數的值

<?php

$y = 1;

$fn1 = fn($x) => $x + $y;

// 相當於 using $y by value:
$fn2 = function ($x) use ($y) {
    return $x + $y;
};

// var_export -- 輸出或返回一個變量的字串表示
var_export($fn1(3)); // 4
?>

2. 箭頭函數自動捕捉變量的值,即使在嵌套的情況下

通常在A程序執行中,尚未結束前又開始執行B程序,B程序結束後,繼續執行A程序,就稱為嵌套。

<?php

$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// 輸出 21
var_export($fn(5)(4));
?>

3. 箭頭函數有效用法例子

和匿名函數一樣,箭頭函數語法同樣允許標準的函數聲明,包括參數和返回類型、缺省值、變量,以及通過引用傳遞和返回。以下都是箭頭函數的有效例子。

<?php

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

?>

4. 來自外部範圍的值不能在箭頭函數內修改

箭頭函數會自動綁定上下文變量,這相當於對箭頭函數內部使用的每一個變量 $x 執行了一個 use($x)。這意味著不可能修改外部作用域的任何值,若要實現對值的修改,可以使用 匿名函數 來替代。

<?php

$x = 1;
$fn = fn() => $x++; // 不會影響 x 的值
$fn();
var_export($x);  // 輸出 1

?>

資料來源: https://www.php.net/


上一篇
[Day12]PHP 可變函數及回傳值
下一篇
[Day14]PHP Class 類別01
系列文
後端新手PHP+Laravel筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言