php的闭包(Closure)匿名函数初探


Posted in PHP onFebruary 14, 2016

提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:

$func = function() {
   
}; //带结束符
可以看到,匿名函数因为没有名字,如果要使用它,需要将其返回给一个变量。匿名函数也像普通函数一样可以声明参数,调用方法也相同:
$func = function( $param ) {
  echo $param;
};
 
$func( 'some string' );
 
//输出:
//some string

顺便提一下,PHP在引入闭包之前,也有一个可以创建匿名函数的函数:create function,但是代码逻辑只能写成字符串,这样看起来很晦涩并且不好维护,所以很少有人用。

 1、实现闭包
将匿名函数在普通函数中当做参数传入,也可以被返回。这就实现了一个简单的闭包。

下边有三个例子

//例一
//在函数里定义一个匿名函数,并且调用它
function printStr() {
  $func = function( $str ) {
    echo $str;
  };
  $func( 'some string' );
}
 
printStr();
 
 
 
//例二
//在函数中把匿名函数返回,并且调用它
function getPrintStrFunc() {
  $func = function( $str ) {
    echo $str;
  };
  return $func;
}
 
$printStrFunc = getPrintStrFunc();
$printStrFunc( 'some string' );
 
 
 
 
//例三
//把匿名函数当做参数传递,并且调用它
function callFunc( $func ) {
  $func( 'some string' );
}
 
$printStrFunc = function( $str ) {
  echo $str;
};
callFunc( $printStrFunc );
 
//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉
callFunc( function( $str ) {
  echo $str;
} );

2、连接闭包和外界变量的关键字:USE
闭包可以保存所在代码块上下文的一些变量和值。PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。

换一个例子看看:

function getMoney() {
  $rmb = 1;
  $dollar = 6;
  $func = function() use ( $rmb ) {
    echo $rmb;
    echo $dollar;
  };
  $func();
}
 
getMoney();
 
//输出:
//1
//报错,找不到dorllar变量

可以看到,dollar没有在use关键字中声明,在这个匿名函数里也就不能获取到它,所以开发中要注意这个问题。

有人可能会想到,是否可以在匿名函数中改变上下文的变量,但我发现是不可以的:

function getMoney() {
  $rmb = 1;
  $func = function() use ( $rmb ) {
    echo $rmb;
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
 
getMoney();
 
//输出:
//1
//1

啊,原来use所引用的也只不过是变量的一个副本而已。但是我想要完全引用变量,而不是复制。

要达到这种效果,其实在变量前加一个 & 符号就可以了:

function getMoney() {
  $rmb = 1;
  $func = function() use ( &$rmb ) {
    echo $rmb;
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
 
getMoney();
 
//输出:
//1
//2

好,这样匿名函数就可以引用上下文的变量了。如果将匿名函数返回给外界,匿名函数会保存use所引用的变量,而外界则不能得到这些变量,这样形成‘闭包'这个概念可能会更清晰一些。

根据描述改变一下上面的例子:

function getMoneyFunc() {
  $rmb = 1;
  $func = function() use ( &$rmb ) {
    echo $rmb;
    //把$rmb的值加1
    $rmb++;
  };
  return $func;
}
 
$getMoney = getMoneyFunc();
$getMoney();
$getMoney();
$getMoney();
 
//输出:
//1
//2
//3

 总结
PHP闭包的特性并没有太大惊喜,其实用CLASS就可以实现类似甚至强大得多的功能,更不能和js的闭包相提并论,只能期待PHP以后对闭包支持的改进。不过匿名函数还是挺有用的,比如在使用preg_replace_callback等之类的函数可以不用在外部声明回调函数了。

小伙伴们是否对PHP的匿名函数也就是闭包函数有了新的认识了呢,希望本文能给大家一些提示,希望大家能够喜欢。

PHP 相关文章推荐
PHP伪造referer实例代码
Sep 20 PHP
修改PHP的memory_limit限制的方法分享
Feb 21 PHP
PHP中的生成XML文件的4种方法分享
Oct 06 PHP
PHP中SimpleXML函数用法分析
Nov 26 PHP
php实现将任意进制数转换成10进制的方法
Apr 17 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
Mar 06 PHP
php实现的简单数据库操作Model类
Nov 16 PHP
Yii2 批量插入、更新数据实例
Mar 15 PHP
PHP基于socket实现的简单客户端和服务端通讯功能示例
Jul 10 PHP
Laravel5.5新特性之友好报错以及展示详解
Aug 13 PHP
PHP实现网站访问量计数器
Oct 27 PHP
laravel返回统一格式错误码问题
Nov 04 PHP
PHP5.3新特性小结
Feb 14 #PHP
PHP解压tar.gz格式文件的方法
Feb 14 #PHP
最新版本PHP 7 vs HHVM 多角度比较
Feb 14 #PHP
PHP使用socket发送HTTP请求的方法
Feb 14 #PHP
PHP闭包函数详解
Feb 13 #PHP
php设计模式之委托模式
Feb 13 #PHP
PHP常用设计模式之委托设计模式
Feb 13 #PHP
You might like
php 正则 过滤html 的超链接
2009/06/02 PHP
ThinkPHP使用Ueditor的方法详解
2016/05/20 PHP
PHP实现时间比较和时间差计算的方法示例
2017/07/24 PHP
PHP使用curl_multi实现并发请求的方法示例
2018/04/29 PHP
php array_chunk()函数用法与注意事项
2019/07/12 PHP
如何用javascript去掉字符串里的所有空格
2007/02/08 Javascript
jsTree树控件(基于jQuery, 超强悍)[推荐]
2009/09/01 Javascript
js变换显示图片的实例
2013/04/16 Javascript
浅析javascript的间隔调用和延时调用
2014/11/12 Javascript
JavaScript DSL 流畅接口(使用链式调用)实例
2015/03/15 Javascript
jQuery Mobile操作HTML5的常用函数总结
2016/05/17 Javascript
利用ES6语法重构React组件详解
2017/03/02 Javascript
基于JavaScript 性能优化技巧心得(分享)
2017/12/11 Javascript
Swiper自定义分页器使用详解
2017/12/28 Javascript
使用express搭建一个简单的查询服务器的方法
2018/02/09 Javascript
webpack dll打包重复问题优化的解决
2018/10/10 Javascript
jQuery+Datatables实现表格批量删除功能【推荐】
2018/10/24 jQuery
vant IndexBar实现的城市列表的示例代码
2019/11/20 Javascript
微信小程序后端实现授权登录
2020/02/24 Javascript
Python使用matplotlib绘制动画的方法
2015/05/20 Python
浅谈终端直接执行py文件,不需要python命令
2017/01/23 Python
Python递归函数定义与用法示例
2017/06/02 Python
Python3 实现文件批量重命名示例代码
2019/06/03 Python
使用WingPro 7 设置Python路径的方法
2019/07/24 Python
selenium2.0中常用的python函数汇总
2019/08/05 Python
对Python中一维向量和一维向量转置相乘的方法详解
2019/08/26 Python
Pytorch evaluation每次运行结果不同的解决
2020/01/02 Python
Pytorch模型转onnx模型实例
2020/01/15 Python
Python中url标签使用知识点总结
2020/01/16 Python
基于python requests selenium爬取excel vba过程解析
2020/08/12 Python
Unix里面如何在后台运行程序
2016/10/14 面试题
CAD制图人员的自荐信
2014/02/07 职场文书
村党支部书记承诺书
2014/05/29 职场文书
打架检讨书
2015/01/27 职场文书
python实现简易名片管理系统
2021/04/11 Python
Python 高级库15 个让新手爱不释手(推荐)
2021/05/15 Python