长期以来,我对回调函数、匿名函数和闭包的概念存在着许多困惑。因此,我决定撰写这篇文章,旨在帮助大家消除对这三个术语的疑惑。首先,让我们从它们的定义和表示方法开始学习。

一、回调函数

回调函数是一种可以作为参数传递给另一个函数的函数。该函数将在特定时间或事件发生时被调用。这类似于现实生活中的场景:你将某事委托给别人,并在对方空闲时得到回应。

下面,让我们通过一个示例来进一步理解回调函数:

function sortNumbers(array $numbers, callable $sortingFunction): array
{
  for ($i = 0; $i < count($numbers) - 1; $i++) {
    for ($j = $i + 1; $j < count($numbers); $j++) {
      if($sortingFunction($numbers[$i],$numbers[$j])){
         $temp = $numbers[$i];
         $numbers[$i] = $numbers[$j];
         $numbers[$j] = $temp;
         }
      }
  }
  return $numbers;
}

注意:所有示例均采用 PHP 语言。 将介绍如何在 PHP 中按升序和降序对数字进行排序。为了方便初学者理解,我们对代码进行了简化和注释。

首先,我们声明了一个名为 sortNumbers 的函数,该函数接受两个参数:

  • numbers:待排序的数字数组
  • callback:用于定义排序逻辑的回调函数

接下来,我们使用嵌套循环来比较数组中的元素:

  • 外循环遍历数组中的每个元素
  • 内循环将索引 “$i” 处的元素与每个后续元素进行比较
$unsortedNumbers = [5, 3, 1, 8, 2];
// 按升序排序
$sortedAscending = sortNumbers($unsortedNumbers,function($a,$b) {
  return $a >$b;
});
print_r($sortedAscending);
// 输出: [1,2,3,5,8]

本节将使用之前定义的 sortNumbers 函数对数字进行升序排序。该函数接受两个参数:

  • unsortedNumbers:待排序的数字数组
  • callback:用于定义排序逻辑的回调函数 回调函数负责比较两个数字,并根据比较结果返回 true 或 false。如果第一个数字应位于第二个数字之前,则返回 true。

为了保持代码简洁,我们直接在函数调用中内联定义了回调函数:

function ascending($a,$b) {
  return $a > $b;
}

 function descending($a,$b) {
  return $a < $b;
}
 $unsortedNumbers = [5, 3, 1, 8, 2];
 $sortedAscending = sortNumbers($unsortedNumbers'ascending');
 print_r($sortedAscending); // 输出: [1, 2, 3, 5, 8]

 $sortedDescending = sortNumbers($unsortedNumbers'descending');
 print_r($sortedDescending); // 输出: [8, 5, 3, 2, 1]

二、匿名函数

匿名函数是指没有函数名的函数,通常使用特殊语法定义。它可以用于创建紧凑的一次性函数,避免在代码中添加不必要的函数声明。匿名函数可以接收参数并存储在变量中。

下面,让我们通过一个示例来进一步理解匿名函数:

 $addNumbers = function(int $a, int $b) {
   return $a + $b;
};

 echo $addNumbers(5, 3); // 输出: 8

这里我创建了一个匿名函数。也就是说,我使用内联函数关键字并且不带函数名称,并将其存储到变量中。请注意,因为这是内联语句,所以代码块末尾需要有分号。这里这个匿名函数可以接受两个参数,并且它应该是整数。然后根据两个参数进行计算并显示结果。

为什么使用匿名函数:

1、提高代码可重用性:
  • 可以创建将其他函数(回调)作为参数的函数,避免为类似任务重复编写代码。
  • 可以根据特定需求定制主函数的行为,促进代码重用,减少代码冗余。
2、增强代码可读性:
  • 可以将复杂逻辑分解为更小、更易管理的单元,每个函数的目的更加清晰。
  • 提高代码的可读性和可维护性。
3、促进代码解耦:
  • 可以将程序的核心逻辑与事件处理或异步操作的具体细节分离。
  • 提高代码的可维护性,降低副作用风险,因为回调函数在其定义范围内运行。

PHP 7.4 引入了箭头函数,这是一种声明匿名函数的新方法。箭头函数在功能上与匿名函数非常相似,但语法更加简洁。

箭头函数使用 fn 关键字定义,然后是参数块的括号,最后是单个表达式的箭头运算符 (=>)。语法如下:

fn(argument) => expression

以下示例将之前的匿名函数重构为箭头函数:

 $addNumbers = fn(int $a, int $b) => $a + $b;

 echo $addNumbers(5, 3); // 输出: 8

箭头函数具有以下优势:

  • 简洁性:语法更加简洁,特别是在只有一个表达式的函数中。
  • 易读性:代码更加易读,特别是对于嵌套函数。

三、闭包

闭包是与匿名函数密切相关的函数,但它具有额外的功能:可以访问其定义所在范围之外的变量。 当一个闭包被创建时,它会捕获其创建时的环境,包括所有可访问的变量。即使该环境在闭包返回后不再存在,闭包仍然可以访问这些变量。

本示例展示了如何使用闭包生成一个平方计算器。

 function generateSquareCalculator(){
   ᄋᄋᄋ$square = function($number) {
     return $number * $number;
   };
     return $square;
}
 $squareCalculator = generateSquareCalculator();
 echo $squareCalculator(5); // 输出: 25

本示例展示了如何使用闭包生成一个乘法器。

 function generateMultiplier($factor){
  return function($number) use ($factor){
    return $number * $factor;
  };
}
 $multiplierByFive = generateMultiplier(5);
 echo $multiplierBy5(10); // 输出: 50

回调函数、匿名函数和闭包是 PHP 中三种重要的函数类型,它们具有不同的特性和应用场景。

1、回调函数是指可以作为参数传递给其他函数的函数。通常用于异步编程、事件处理等场景。

2、匿名函数是没有函数名的函数,通常用于简短的一次性任务或针对特定上下文定制的函数。

3、闭包是能够访问其创建上下文中的变量的函数,即使该上下文已经消失。

本文对回调函数、匿名函数和闭包进行了概述,并介绍了它们的应用场景。掌握这些函数类型的特性和应用场景可以显著提高您的 PHP 编程技巧。