PHP中的闭包小谈
接触PHP一段时间以来,我一直以为这是一种基于函数式编程的语言是没有闭包这种东西的,但事实上却颠覆了我的想法,PHP竟然有闭包,下面我们一起来接触一下PHP的所谓的闭包。
根据PHP官网的定义来看,闭包(closure)又可以叫做匿名函数(Anonymous function),其实我们知道在JS中,闭包和匿名函数有着一定的区别,但是在PHP中却等同了,那么这肯定有一些区别的,那么我们和JS当中的闭包对比的来看看。
1、语句结构
在JS中,闭包和普通的函数定义没有什么区别,但是在PHP中,由于存在函数内部不能访问全局作用的,所以就需要一种可以引入上一级作用域的语法结构,这种就是
function () use () {}
将需要引入到这个函数作用于内的变量写入到use的括号里面就可以了,举个例子
<?php $a = 1; $closure = function () use ($a) {
echo $a;
}; $closure(); ?>
输出的结果为
1
这次就实现了闭包的功能了,可以和上级作用域产生了联系了
2、变量执行的时候是运行时赋值还是函数声明的时候赋的值?
学过JS的到这里一定认为这个$a变量当变化的时候,根据JS引用的理论,函数执行的结果也是变化的,但事实究竟是这样么?看例子:
<?php $a = 1; $closure = function () use ($a) {
echo $a;
}; $closure(); $a=2; $closure(); ?>
大家猜猜结果会是什么?
1 1
哎??为什么不是 1 2 呢?
因为对于PHP来说的闭包当声明闭包的时候,就已经将值重新开辟了一块内存赋值给了use中的$a所以,不过外部的$a怎么变,闭包执行的结果是不变的,那么我们怎么能让他变化呢?
先给大家一个提示,PHP实现闭包的本质其实是将这个特殊的函数转换成了一个类。
说到这里,大家是不是有一点明白了呢?既然是类,那么我们可以使用引用来传递use当中的值。
让我们再试一下
<?php $a = 1; $closure = function () use (&$a) {//注意这里,加了一个&
echo $a;
}; $closure(); $a=2; $closure(); ?>
再运行一下看看
1 2
这次结果对了吧。
不仅如此,引用之后,如果在闭包当中修改引入的变量值,原本的变量的值也会修改的,但是不过不加&,那么在闭包中修改变量的值得时候,即使这次修改有效了,下次重新运行闭包函数后又会回到之前的值,相当于没有修改。举个例子:
不加&:
<?php
$a = 1;
$closure = function () use ($a) {
$a++;
echo $a,' ';
};
$closure();
$closure();
$a=-5;
$closure();
$closure();
?>
输出为:
2 2 2 2
加了&之后
输出为
2 3 -4 -3
总结:
对应PHP中的闭包,和JS中的闭包还是有本质的区别的,JS的闭包是语言原生支持的,所以感觉比较符合人的思考方式,而PHP得闭包就是将闭包的这种特性抽象成了类的方式,然后以类的形式进行处理,毕竟是抽象出来的,还不是很符合人们的思考方式。
在接触了PHP的闭包之后,我深深的觉得PHP真是杂啊………………
PS:
1、不要忘记了在闭包的赋值语句最后面的分号,毕竟这是一个语句,还要是有分号的。
2、对于函数的传入参数等东西,和普通的参数写法是一样的。
3、要注意函数调用的时候不要忘记了$,因为闭包函数的本质还是一个变量的,不过是一个可以执行的变量了而已。如果去掉$,PHP解释器将会认为这是一个函数而不是一个闭包函数从而出错。
4、除了上面的那几点和JS的不同以外,其他的都是可以的,比如可以作为函数的返回值等等的内容。
PHP中的闭包小谈的更多相关文章
- js 中继承方式小谈
题外话 前段时间面试中笔试题有这道题目: 请实现一个继承链,要求如下: 构造函数A():构造函数中有consoleA方法,可以实现console.log("a") 实例对象 a:a ...
- 让你分分钟学会Javascript中的闭包
Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...
- Javascript中的闭包(转载)
前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...
- 狗日的Javascript中的闭包
前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 【Unity游戏开发】浅谈Lua和C#中的闭包
一.前言 目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#.通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑.这样既能在保持一定的游戏运行效率的同 ...
- 浅谈 .NET 中的对象引用、非托管指针和托管指针 理解C#中的闭包
浅谈 .NET 中的对象引用.非托管指针和托管指针 目录 前言 一.对象引用 二.值传递和引用传递 三.初识托管指针和非托管指针 四.非托管指针 1.非托管指针不能指向对象引用 2.类成员指针 五 ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 关于for循环中的闭包问题
还是昨天的那个简单的小项目,已经花了一天的时间了 - - .从&&的用法,到CSStext,到今天马上要谈的闭包(closure),通过一个小东西,真真发现了自己的各方面不足.昨天发完 ...
随机推荐
- git 关于commit命令的修改
1 修改最后一次提交的信息 git commit --amend 2 对于历史提交 git rebase -i HEAD~5 没毛病,
- Raspberry Pi 开机启动QT程序
https://blog.csdn.net/coekjin/article/details/52498212 https://blog.csdn.net/dubuzherui/article/deta ...
- psql 命令
(1)使用命令行连接数据库 psql -U postgres -h localhost -p 5433 (2)列出所有的数据库 \l -- 查看所有数据库 (3)进入某个数据库 \c name -- ...
- dwr中的部分问题和总结
2015-9-1 1.dwr设置同步异步:DWREngine.setAsync(false);//dwr设置为同步 --->使用目的是堵塞js,因为设置这样是为了js进行java的后台数据获取. ...
- haproxy的代理中继用法
背景: 现有: 一台baidu/ali/tecent云服务器A(地址为a.a.a.a); 一台VPS B(地址为b.b.b.b), B中搭建有ss,监听端口为8000. 需求: 一:使用A做跳板机访问 ...
- 六、原型(Prototype)模式
原型模式是对象的创建模式,通过给出一个原型对象来指明所要创建的对象的类型.然后用复制这个原型对象的方法来创建出更多同类型的对象. 原型模式可以不用重新初始化对象,而动态的获取对象运行时的状态.使用原型 ...
- MySql为某个表增加rownumber
在mySql中,假设表名为tblA,则 select @x:=@x+1 as rownumber, a.* from (select @x:=0) b, tblA a 此语句执行后,则每行数据之前都会 ...
- Array Beauty
Array Beauty 给出一个长度为n的序列\(\{a_i\}\),定义一个序列的权值为其中元素两两之差的绝对值的最小值,询问\(\{a_i\}\)长度为K的子序列的权值之和\(\% 998244 ...
- layer.msg的使用
源码: layer.msg('只想弱弱提示'); layer.msg('表情提示', {icon: 6}); layer.msg('关闭后想做些什么呢', function(){ //自动执行这里面的 ...
- Magento多语言注意事项
Magento一般使用CSV文件方式翻译国际化词条 一般用法是代码中: <?php echo Mage::helper("module_name")->__('Item ...