浅析PHP中的闭包和匿名函数


Posted in PHP onDecember 25, 2017

闭包是指在创建时封装周围状态的函数。即使闭包所在的环境不存在了,闭包中封装的状态依然存在。

匿名函数就是没有名称的函数。匿名函数可以赋值给变量,还能像其他任何PHP对象那样传递。不过匿名函数仍是函数,因此可以调用,还可以传入参数。匿名函数特别适合作为函数或方法的回调。

注意:理论上讲,闭包和匿名函数是不同的概念。不过,PHP将其视作相同的概念。所以,我们提到闭包时,指的也是匿名函数,反之亦然。

PHP闭包和匿名函数使用的句法与普通函数相同,但闭包和匿名函数其实是 伪装成函数的对象(Closure类的实例) 。

创建闭包

$closure = function($name){
  return sprintf("Hello %s", $name);
}
echo $closure("jerry");
// 检测$closure变量是否是一个闭包
var_dump($closure instanceof Closure);

以上代码创建了一个闭包对象,然后将其赋值给 $closure 变量。闭包和普通的PHP函数很像,使用的句法相同,也接收参数,而且能返回值。

说明:我们之所以能够调用 $closure 变量,是因为这个变量的值是一个闭包,而且闭包对象实现了 __invoke() 魔术方法。只要变量名后有 () ,PHP就会查找并调用 __invoke() 方法。

使用闭包

我们通常把PHP闭包当做当做函数和方法的回调使用。很多PHP函数都会用到回调函数,例如 array_map() preg_replace_callback() .如下示例,我们将用 array_map() 处理数组,将数组每一项自增1:

$nubmers = array_map(function($number){
  return $number++;
}, [1,2,3]);
var_dump($numbers);

附加状态

PHP闭包不会像真正的javascrypt闭包那样自动封装应用的状态,我们必须手动调用闭包对象的 bindTo() 方法或者使用 use 关键字,把状态附加到PHP闭包上。

使用 use 关键字

使用 use 关键字来附加闭包状态更加常见,因此我们先来看这种方式。使用 use 关键字把变量附加闭包上时,附加的变量会记住附加时赋给它的值。

function Car ($name){
  return function($statu)use($name){
    return sprintf("Car %s is %s", $name, $statu); 
  }
}
// 将车名封装在闭包中
$car = Car("bmw");
// 调用车的动作
// 输出--> "bmw is running"
echo $car("running");

注意:使用 use 关键字可以把多个参数传入闭包,此时要像PHP函数或方法的参数一样,使用逗号分隔多个参数。

使用 bindTo() 方法附加闭包的状态

与其它PHP对象类似,每个闭包实例都可以使用 $this 关键字获取闭包的内部状态。闭包对象的默认状态没什么用,不过有一个 __invoke() 魔术方法和 bindTo() 方法。

bindTo() 方法为闭包增加了一些有趣的潜力。我们可以使用这个方法把 Closure 对象的内部状态绑定到其它对象上。

bindTo() 方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中受保护和私有的成员变量。

class TestClosure
{
  private $name=[];
  private $age;
  private $sex;
  public function addPerson($name, $personCallback){
    // 将闭包对象绑定当前实例
    $this->name[$name] = $personCallback->bindTo($this, __CLASS__);
  }
  public function display($name){
    foreach ($this->name as $key => $callback){
      if($key == $name){
        // 执行闭包对象,将闭包状态附加到类
        $callback();
      }
    }
    echo "name : {$name}\n";
    echo "age : {$this->age}\n";
    echo "sex : {$this->sex}\n";
  }
}
$person = new TestClosure();
$person->addPerson("jerry", function(){
  $this->age = 19;
  $this->sex = "man";
});
$person->display("jerry");
/** output
name : jerry
age : 19
sex : man
*/

总结

以上所述是小编给大家介绍的PHP中的闭包和匿名函数,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

PHP 相关文章推荐
php基础知识:函数基础知识
Dec 13 PHP
PHP版网站缓存加快打开速度的方法分享
Jun 03 PHP
php计算十二星座的函数代码
Aug 21 PHP
php-cli简介(不会Shell语言一样用Shell)
Jun 03 PHP
php分页函数示例代码分享
Feb 24 PHP
php使用session二维数组实例
Nov 06 PHP
php中HTTP_REFERER函数用法实例
Nov 21 PHP
php页面缓存方法小结
Jan 10 PHP
php实现无限级分类(递归方法)
Aug 06 PHP
php猜单词游戏
Sep 29 PHP
php自动加载方式集合
Apr 04 PHP
php中上传文件的的解决方案
Sep 25 PHP
thinkphp5 加载静态资源路径与常量的方法
Dec 24 #PHP
PHP读取并输出XML文件数据的简单实现方法
Dec 22 #PHP
ajax+php实现无刷新验证手机号的实例
Dec 22 #PHP
Thinkphp5行为使用方法汇总
Dec 21 #PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
Dec 21 #PHP
Laravel 5.5基于内置的Auth模块实现前后台登陆详解
Dec 21 #PHP
PHP实现生成模糊图片的方法示例
Dec 21 #PHP
You might like
解析PHP正则提取或替换img标记属性
2013/06/26 PHP
PHP SPL使用方法和他的威力
2013/11/12 PHP
Thinkphp 空操作、空控制器、命名空间(详解)
2017/05/05 PHP
php实现的数组转xml案例分析
2019/09/28 PHP
基于JQuery模仿苹果桌面的Dock效果(初级版)
2012/10/15 Javascript
jquery多行滚动/向左或向上滚动/响应鼠标实现思路及代码
2013/01/23 Javascript
原生Js页面滚动延迟加载图片实现原理及过程
2013/06/24 Javascript
js Map List 遍历使用示例
2013/07/10 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
2014/01/10 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
2015/03/20 Javascript
javascript实现日期时间动态显示示例代码
2015/09/08 Javascript
简单实现nodejs上传功能
2017/01/14 NodeJs
详解AngularJS中$filter过滤器使用(自定义过滤器)
2017/02/04 Javascript
原生JavaScript实现的简单省市县三级联动功能示例
2017/05/27 Javascript
react-native动态切换tab组件的方法
2018/07/07 Javascript
nodejs如何在package.json中设置多条启动命令
2020/03/16 NodeJs
JavaScript代码实现简单计算器
2020/12/27 Javascript
Python字符串拼接、截取及替换方法总结分析
2016/04/13 Python
判断网页编码的方法python版
2016/08/12 Python
Python编程二分法实现冒泡算法+快速排序代码示例
2018/01/15 Python
Python爬虫信息输入及页面的切换方法
2018/05/11 Python
在Python中使用defaultdict初始化字典以及应用方法
2018/10/31 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
Django中Middleware中的函数详解
2019/07/18 Python
python+numpy实现的基本矩阵操作示例
2019/07/19 Python
HttpServlet类中的主要方法都有哪些?各自的作用是什么?
2014/03/16 面试题
签约仪式主持词
2014/03/19 职场文书
服装设计师求职信
2014/06/04 职场文书
孔子观后感
2015/06/08 职场文书
第一军规观后感
2015/06/12 职场文书
重温入党誓词主持词
2015/06/29 职场文书
幼儿园保教工作总结2015
2015/10/15 职场文书
开学第一周日记(三篇范文)
2019/08/23 职场文书
spring boot中nativeQuery的用法
2021/07/26 Java/Android
python中super()函数的理解与基本使用
2021/08/30 Python
TypeScript 内置高级类型编程示例
2022/09/23 Javascript