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投票程序源码
Mar 11 PHP
php下使用strpos需要注意 === 运算符
Jul 17 PHP
php懒人函数 自动添加数据
Jun 28 PHP
用PHP实现小写金额转换大写金额的代码(精确到分)
Jan 10 PHP
iis下php mail函数的sendmail配置方法(官方推荐)
Apr 25 PHP
PHP中对于浮点型的数据需要用不同的方法解决
Mar 11 PHP
php实现建立多层级目录的方法
Jul 19 PHP
php简单实现MVC
Feb 05 PHP
PHP实现网站访问量计数器
Oct 27 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
May 06 PHP
tp5框架的增删改查操作示例
Oct 31 PHP
laravel与thinkphp之间的区别与优缺点
Mar 02 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 md5下16位和32位的实现代码
2008/04/09 PHP
用mysql触发器自动更新memcache的实现代码
2009/10/11 PHP
php实现的遍历文件夹下所有文件,编辑删除
2010/01/05 PHP
PHP将DateTime对象转化为友好时间显示的实现代码
2011/09/20 PHP
thinkphp的URL路由规则与配置实例
2014/11/26 PHP
php封装的表单验证类完整实例
2016/10/19 PHP
Laravel 5.4重新登录实现跳转到登录前页面的原理和方法
2017/07/13 PHP
php创建类并调用的实例方法
2019/09/25 PHP
实现复选框全选/全不选切换
2006/12/23 Javascript
JavaScript isPrototypeOf和hasOwnProperty使用区别
2010/03/04 Javascript
javascript instanceof 内部机制探析
2010/10/15 Javascript
关于innerHTML后丢失动态绑定的EVENT问题解决方法
2013/05/19 Javascript
Javascript基础教程之变量
2015/01/18 Javascript
JavaScript数据类型检测代码分享
2015/01/26 Javascript
浅谈JS中String()与 .toString()的区别
2016/10/20 Javascript
jQuery插件HighCharts绘制2D带Label的折线图效果示例【附demo源码下载】
2017/03/08 Javascript
通过jquery的ajax请求本地的json文件方法
2018/08/08 jQuery
[01:10:02]IG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
跟老齐学Python之关于类的初步认识
2014/10/11 Python
仅用500行Python代码实现一个英文解析器的教程
2015/04/02 Python
python/sympy求解矩阵方程的方法
2018/11/08 Python
python数据处理 根据颜色对图片进行分类的方法
2018/12/08 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
2019/05/04 Python
Django框架模板的使用方法示例
2019/05/25 Python
pytorch 实现L2和L1正则化regularization的操作
2021/03/03 Python
html5指南-6.如何创建离线web应用程序实现离线访问
2013/01/07 HTML / CSS
HTML5 预加载让页面得以快速呈现
2013/08/13 HTML / CSS
Html5实现二维码扫描并解析
2016/01/20 HTML / CSS
SVG实现多彩圆环倒计时效果的示例代码
2017/11/21 HTML / CSS
Java基础知识面试要点
2016/07/29 面试题
师范教师毕业鉴定
2014/01/13 职场文书
优秀毕业生自我鉴定
2014/01/19 职场文书
创先争优活动党员公开承诺书
2014/08/29 职场文书
光棍节联谊晚会活动策划书
2014/10/10 职场文书
Redis实现订单自动过期功能的示例代码
2021/05/08 Redis
解析MySQL索引的作用
2022/03/03 MySQL