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初学者头疼问题总结
Jul 08 PHP
php 前一天或后一天的日期
Jun 28 PHP
攻克CakePHP系列一 连接MySQL数据库
Oct 22 PHP
PHP Document 代码注释规范
Apr 13 PHP
php iconv() : Detected an illegal character in input string
Dec 05 PHP
基于Zookeeper的使用详解
May 02 PHP
PHP实现服务器状态监控的方法
Dec 09 PHP
PHP unlink与rmdir删除目录及目录下所有文件实例代码
Feb 07 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
Jun 13 PHP
php提供实现反射的方法和实例代码
Sep 17 PHP
php实现根据身份证获取精准年龄
Feb 26 PHP
PHP 实现 WebSocket 协议原理与应用详解
Apr 22 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关于IE下的iframe跨域导致session丢失问题解决方法
2013/10/10 PHP
Drupal7连接多个数据库及常见问题解决
2014/03/02 PHP
php中实现用数组妩媚地生成要执行的sql语句
2015/07/10 PHP
javascript SocialHistory 检查访问者是否访问过某站点
2008/08/02 Javascript
基于jquery的点击链接插入链接内容的代码
2012/07/31 Javascript
javascript中方便增删改cookie的一个类
2012/10/11 Javascript
window.onload和$(function(){})的区别介绍
2013/10/30 Javascript
js实现遍历含有input的table实例
2015/12/07 Javascript
基于JavaScript实现定时跳转到指定页面
2016/01/01 Javascript
浅谈javascript 函数表达式和函数声明的区别
2016/01/05 Javascript
JavaScript中this的四个绑定规则总结
2016/09/26 Javascript
jQuery 添加样式属性的优先级别方法(推荐)
2017/06/08 jQuery
webpack 4.0.0-beta.0版本新特性介绍
2018/02/10 Javascript
angularJS的radio实现单项二选一的使用方法
2018/02/28 Javascript
在 Vue 项目中引入 tinymce 富文本编辑器的完整代码
2018/05/04 Javascript
分享5个顶级的JavaScript Ajax组件库
2018/09/16 Javascript
理理Vue细节(推荐)
2019/04/16 Javascript
JS实现扫码枪扫描二维码功能
2020/01/03 Javascript
python3爬虫学习之数据存储txt的案例详解
2019/04/24 Python
Python实现代码块儿折叠
2020/04/15 Python
简单了解python列表和元组的区别
2020/05/14 Python
python 动态渲染 mysql 配置文件的示例
2020/11/20 Python
日本著名的服饰鞋帽综合类购物网站:MAGASEEK
2019/01/09 全球购物
运动鞋、足球鞋和慕尼黑球衣:Sport Münzinger
2019/08/26 全球购物
Carmen Sol官网:购买果冻鞋、手袋和配件
2021/01/01 全球购物
假日旅行社实习自我鉴定
2013/09/24 职场文书
数控专业推荐信范文
2013/12/02 职场文书
公司庆典邀请函范文
2014/01/13 职场文书
法人授权委托书样本
2014/09/19 职场文书
幼儿园园长新年寄语2015
2014/12/08 职场文书
瞿秋白纪念馆观后感
2015/06/10 职场文书
保护环境的宣传语
2015/07/13 职场文书
2016年班主任培训心得体会
2016/01/07 职场文书
企业管理制度设计时要注意的几种“常见病”!
2019/04/19 职场文书
python实现图片九宫格分割的示例
2021/04/25 Python
解决Pytorch修改预训练模型时遇到key不匹配的情况
2021/06/05 Python