PHP之闭包详解
匿名函数
提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:
$func = function() {
}; //带结束符
可以看到,匿名函数因为没有名字,如果要使用它,需要将其返回给一个变量。匿名函数也像普通函数一样可以声明参数,调用方法也相同:
$func = function( $param ) {
echo $param;
};$func( 'some string' );
//输出:
//some string
顺便提一下,PHP在引入闭包之前,也有一个可以创建匿名函数的函数:create function,但是代码逻辑只能写成字符串,这样看起来很晦涩并且不好维护,所以很少有人用。
实现闭包
将匿名函数在普通函数中当做参数传入,也可以被返回。这就实现了一个简单的闭包。
下边有三个例子
//例一
//在函数里定义一个匿名函数,并且调用它
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;
} );
连接闭包和外界变量的关键字:USE
function getMoney() {
$rmb = 1;
$dollar = 6;
$func = function() use ( $rmb ) {
echo $rmb;
echo $dollar;
};
$func();
}getMoney();
//输出:
//1
//报错,找不到dorllar变量
闭包可以保存所在代码块上下文的一些变量和值。PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。 换一个例子看看:
可以看到,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等之类的函数可以不用在外部声明回调函数了。
本文链接地址:http://www.zhaoyafei.cn//index.php/home/article/articleinfo.html?id=21
本文属于转载,真诚推荐http://www.zhaoyafei.cn(赵亚飞)的个人博客网站,写的真的非常不错,真诚推荐!
PHP之闭包详解的更多相关文章
- Python闭包详解
Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...
- Swift 中的Closures(闭包)详解
Swift 中的Closures(闭包)详解 在Swift没有发布之前,所有人使用OC语言编写Cocoa上的程序,而其中经常被人们讨论的其中之一 -- Block 一直备受大家的喜爱.在Swift中, ...
- PHP中的闭包详解
PHP闭包(Closure)使用详解 作者: 字体:[增加 减小] 类型:转载 时间:2013-05-02我要评论 本篇文章介绍了,PHP闭包(Closure)的使用介绍,需要的朋友参考下 不知不 ...
- js闭包详解
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数 ...
- JavaScript之作用域与闭包详解
前言: JavaScript是一种应用非常广泛的语言,其也有一些自身特点和优势,本文重在讲述其作用域机制以及闭包,会从一些实例来探讨其机理. 作用域在JavaScript程序员日常使用中有不同的含义, ...
- JS重点特性——闭包详解
闭包特性:可以让定义好的函数作用域在调用时发生改变,具体说,调用运行时,可以让(定义时)作用域外其他函数访问到本函数的局部变量甚至参数.举例代码如下: <!DOCTYPE html> &l ...
- JavaScript 闭包详解
一.Javascript闭包的用途 事实上,通过使用闭包,我们可以做很多事情.比如模拟面向对象的代码风格:更优雅,更简洁的表达出代码:在某些方面提升代码的执行效率. 1.匿名自执行函数 我们知道所有的 ...
- js 闭包 详解
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数 ...
- javascript闭包详解
以前写过一篇关于javascript闭包的随笔,javascript闭包,但是写的不够详细,也没有体现出闭包的强大之处.故作此篇. 众所周知,javascript没有块级作用域,只有函数作用域.那就意 ...
- JavaScript的闭包详解
(1)定义: 函数内部返回一个函数,返回出来的这个函数叫做被我们称之为闭包(个人理解的最简单的表现形式,) (2)为什么要使用闭包呢? 局部变量在函数执行完之后就会被GC回收,有时候我们想在外部访问内 ...
随机推荐
- 关于Apache+PHP+MySQL的安装
除了在安装MySQL的时候花了三天的时间,也学习了如何看错误日志,如何看配置文件等, Apache+PHP的安装都比较顺利,主要是要按照一个文档来安装,不要东拼西凑, 个人认为这篇“百度经验”写得很好 ...
- JavaScript总结之鼠标划过弹出div单击出现对话框
为了满足他们的永无止境的要求,我可谓是任劳任怨啊,累断了双手,看瞎了双眼.这个是来写鼠标划过一个按钮,然后弹出一个小提示框解释,另外根据radio是否选中,判断点击后如何执行,然后执行之后再有一个确认 ...
- jQuery 随滚动条滚动效果 (固定版)
//侧栏随动 var rollStart = $('.feed-mail'), //滚动到此区块的时候开始随动 rollSet = $('.search,.weibo,.group,.feed-mai ...
- UIALertView与UIAlertViewDelegate的基本用法
首先,视图控制器必须得实现协议UIAlertViewDelegate中的方法,并指定delegate为self,才能使弹出的Alert窗口响应点击事件. 具体代码如下: ViewController. ...
- Messenger类的使用
一.Messenger类 作用:类似Message类,但是是跨进程使用的. 解析:它的底层是由AIDL实现的,从构造方法可以看出 //Service使用 public Messenger(Handle ...
- 实现JSON数据的存储和读取
事前准备: //创建一个Crime类 public class Crime { private String mTitle; private UUID mUUID; private Date mDat ...
- Android项目记录点滴
服务器端:(根据Apache POI库函数其中SlideShow表示PPT文档,Slide表示某一张幻灯片) 1.先把电脑中的PPT文件读入到一个字节数组中.(输入流-->字节数组-->输 ...
- block,inline,inline-block
block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div>, <p>, <h1>, ...
- opencv如何截取子图像
首先用GetSubRect函数确定子图像的区域 GetSubRect 返回输入的图像或矩阵的矩形数组子集的矩阵头 CvMat* cvGetSubRect( const CvArr* arr, CvM ...
- Mindjet 一打开鼠标就动不了解决方法
在网上查找了一下相关资料,这个主要是Mindjet不支持64位系统造成的,其实就和Windows tablet pc input 这个服务相冲突造成的,临时的解决方法是,win+r (别告诉我你不知道 ...