浅析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面向对象全攻略 (十二) 抽象方法和抽象类
Sep 30 PHP
认识并使用PHP超级全局变量
Jan 26 PHP
PHP file_exists问题杂谈
May 07 PHP
PHP 之Section与Cookie使用总结
Sep 14 PHP
解析php file_exists无效的解决办法
Jun 26 PHP
浅析PHP原理之变量分离/引用(Variables Separation)
Aug 09 PHP
PHP获取文件相对路径的方法
Feb 26 PHP
php动态函数调用方法
May 21 PHP
深入php内核之php in array
Nov 10 PHP
PHP实现的数独求解问题示例
Apr 18 PHP
php递归函数怎么用才有效
Feb 24 PHP
PHP fclose函数用法总结
Feb 15 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实现的替换敏感字符串类实例
2014/09/22 PHP
PHP实现Javascript中的escape及unescape函数代码分享
2015/02/10 PHP
PHP实现判断数组是一维、二维或几维的方法
2017/02/06 PHP
XHTML-Strict 内允许出现的标签
2006/12/11 Javascript
javascript add event remove event
2008/04/07 Javascript
IE 下的只读 innerHTML
2009/08/21 Javascript
在Windows上安装Node.js模块的方法
2011/09/25 Javascript
javascript 进阶篇1 正则表达式,cookie管理,userData
2012/03/14 Javascript
Javascript实现页面跳转的几种方式分享
2013/10/26 Javascript
javascript使用avalon绑定实现checkbox全选
2015/05/06 Javascript
每天一篇javascript学习小结(Function对象)
2015/11/16 Javascript
详解vue-Resource(与后端数据交互)
2017/01/16 Javascript
JS 实现banner图片轮播效果(鼠标事件)
2017/08/04 Javascript
简单的三步vuex入门
2018/05/20 Javascript
微信小程序自定义对话框弹出和隐藏动画
2018/07/19 Javascript
用jQuery将JavaScript对象转换为querystring查询字符串的方法
2018/11/12 jQuery
vue.js的双向数据绑定Object.defineProperty方法的神奇之处
2019/01/18 Javascript
node.js中express模块创建服务器和http模块客户端发请求
2019/03/06 Javascript
Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式功能
2020/04/09 Javascript
linux下python抓屏实现方法
2015/05/22 Python
深入讲解Python函数中参数的使用及默认参数的陷阱
2016/03/13 Python
浅析Python编写函数装饰器
2016/03/18 Python
Python基于回溯法子集树模板解决野人与传教士问题示例
2017/09/11 Python
Python中摘要算法MD5,SHA1简介及应用实例代码
2018/01/09 Python
基于MTCNN/TensorFlow实现人脸检测
2018/05/24 Python
python实现根据指定字符截取对应的行的内容方法
2018/10/23 Python
Django数据库连接丢失问题的解决方法
2018/12/29 Python
Selenium+Python 自动化操控登录界面实例(有简单验证码图片校验)
2019/06/28 Python
Django框架视图函数设计示例
2019/07/29 Python
Python for循环与getitem的关系详解
2020/01/02 Python
企业管理培训感言
2014/01/27 职场文书
大学开学计划书
2014/04/30 职场文书
我的教育故事演讲稿
2014/05/04 职场文书
民间个人借款协议书
2014/09/30 职场文书
大队委员竞选稿
2015/11/20 职场文书
团队合作精神学习心得体会
2016/01/19 职场文书