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 similar_text 字符串的相似性比较函数
May 26 PHP
php入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
Jul 14 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
Jan 23 PHP
PHP不用第三变量交换2个变量的值的解决方法
Jun 02 PHP
CI框架中$this->load->library()用法分析
May 18 PHP
php实现和c#一致的DES加密解密实例
Jul 24 PHP
Laravel中使用Queue的最基本操作教程
Dec 27 PHP
Laravel中unique和exists验证规则的优化详解
Jan 28 PHP
Ajax请求PHP后台接口返回信息的实例代码
Aug 21 PHP
php两点地理坐标距离的计算方法
Dec 29 PHP
thinkphp3.2同时连接两个数据库的简单方法
Aug 13 PHP
php引用传递
Apr 01 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数组函数array_walk用法示例
2016/05/26 PHP
php表单习惯用的正则表达式
2017/10/11 PHP
phpStudy vscode 搭建debug调试的教程详解
2020/07/28 PHP
JavaScript的目的分析
2007/01/05 Javascript
一个网马的tips实现分析
2010/11/28 Javascript
juqery 学习之五 文档处理 包裹、替换、删除、复制
2011/02/11 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
2013/08/28 Javascript
Ajax局部更新导致JS事件重复触发问题的解决方法
2014/10/14 Javascript
angularJS 中$scope方法使用指南
2015/02/09 Javascript
JS自定义选项卡函数及用法实例分析
2015/09/02 Javascript
javascript嵌套函数和在函数内调用外部函数的区别分析
2016/01/31 Javascript
使用jquery.qrcode.min.js实现中文转化二维码
2016/03/11 Javascript
搭建Bootstrap离线文档的方法
2016/12/02 Javascript
JavaScript笛卡尔积超简单实现算法示例
2018/07/30 Javascript
Vue中的组件及路由使用实例代码详解
2019/05/22 Javascript
vue+elementUI实现图片上传功能
2019/08/20 Javascript
[02:43]DOTA2英雄基础教程 圣堂刺客
2013/12/09 DOTA
Python实现配置文件备份的方法
2015/07/30 Python
python笔记:mysql、redis操作方法
2017/06/28 Python
详解python中递归函数
2019/04/16 Python
python3.7实现云之讯、聚合短信平台的短信发送功能
2019/09/26 Python
Python倒排索引之查找包含某主题或单词的文件
2019/11/13 Python
python PIL模块的基本使用
2020/09/29 Python
Python将QQ聊天记录生成词云的示例代码
2021/02/10 Python
浅谈HTML5 defer和async的区别
2016/06/07 HTML / CSS
.NET现在共支持多少种语言
2014/02/26 面试题
Java的类与C++的类有什么不同
2014/01/18 面试题
理货员的岗位职责
2013/11/23 职场文书
赵乐秦在党的群众路线教育实践活动总结大会上的讲话稿
2014/10/25 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
单位综合评价意见
2015/06/05 职场文书
商务宴会祝酒词
2015/08/11 职场文书
Springboot-cli 开发脚手架,权限认证,附demo演示
2022/04/28 Java/Android
Nginx如何配置根据路径转发详解
2022/07/23 Servers
MySQL中TIMESTAMP类型返回日期时间数据中带有T的解决
2022/12/24 MySQL