浅析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 相关文章推荐
PR值查询 | PageRank 查询
Dec 20 PHP
收藏的PHP常用函数 推荐收藏保存
Feb 21 PHP
php中防止恶意刷新页面的代码小结
Oct 31 PHP
基于php缓存的详解
May 15 PHP
PHP中的魔术方法总结和使用实例
May 11 PHP
PHP模板引擎smarty详细介绍
May 26 PHP
深入php内核之php in array
Nov 10 PHP
php+ajax实现无刷新分页
Nov 18 PHP
php 三大特点:封装,继承,多态
Feb 19 PHP
PHP基于ICU扩展intl快速实现汉字转拼音及按拼音首字母分组排序的方法
May 03 PHP
PHP接口继承及接口多继承原理与实现方法详解
Oct 18 PHP
php判断IP地址是否在多个IP段内
Aug 18 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中显示数组与对象的实现代码
2011/04/18 PHP
thinkphp,onethink和thinkox中验证码不显示的解决方法分析
2016/06/06 PHP
php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
2018/09/28 PHP
Laravel项目中timeAgo字段语言转换的改善方法示例
2019/09/16 PHP
JSON传递bool类型数据的处理方式介绍
2013/09/18 Javascript
Ext4.2的Ext.grid.plugin.RowExpander无法触发事件解决办法
2014/08/15 Javascript
jQuery实现ajax调用WCF服务的方法(附带demo下载)
2015/12/04 Javascript
javascript实现非常简单的小数取整功能示例
2017/06/13 Javascript
ReactJs实现树形结构的数据显示的组件的示例
2017/08/18 Javascript
bootstrap-table实现服务器分页的示例 (spring 后台)
2017/09/01 Javascript
vue实现手机号码抽奖上下滚动动画示例
2017/10/18 Javascript
微信小程序使用Promise简化回调
2018/02/06 Javascript
vue-cli扩展多模块打包的示例代码
2018/04/09 Javascript
微信小程序手机号码验证功能的实例代码
2018/08/28 Javascript
vue使用@scroll监听滚动事件时,@scroll无效问题的解决方法详解
2019/10/15 Javascript
jquery实现点击弹出对话框
2020/02/08 jQuery
JavaScript缺少insertAfter解决方案
2020/07/03 Javascript
通过实例解析js可枚举属性与不可枚举属性
2020/12/02 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
js实现碰撞检测
2021/01/29 Javascript
完美解决Python2操作中文名文件乱码的问题
2017/01/04 Python
Python编写Windows Service服务程序
2018/01/04 Python
详解Python3注释知识点
2019/02/19 Python
python3 使用traceback定位异常实例
2020/03/09 Python
python 实现朴素贝叶斯算法的示例
2020/09/30 Python
如何用Python编写一个电子考勤系统
2021/02/08 Python
手把手教你用纯css3实现轮播图效果实例
2017/05/04 HTML / CSS
localStorage的过期时间设置的方法详解
2018/11/26 HTML / CSS
印度领先的眼镜电子商务网站:Lenskart
2019/12/16 全球购物
成教自我鉴定
2013/10/27 职场文书
大学校务公开实施方案
2014/03/31 职场文书
机械加工与数控专业自荐书
2014/06/04 职场文书
经济类毕业生求职信
2014/06/26 职场文书
优秀党员学习焦裕禄精神思想汇报范文
2014/09/10 职场文书
政法干警核心价值观心得体会
2014/09/11 职场文书
个人作风建设自查报告
2014/10/22 职场文书