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),通过一个小东西,真真发现了自己的各方面不足.昨天发完 ...
随机推荐
- ubuntu中搭建基本的开发环境
1.搭建基本开发环境: sudo apt-get install build-essential 2.安装语法.词法分析器 sudo apt-get install bison flex 3.安装C函 ...
- if (user?.Identity?.IsAuthenticated ?? false)这几个问号分别都代表啥意思?
if (user?.Identity?.IsAuthenticated ?? false)这几个问号分别都代表啥意思? 0 悬赏园豆:5 [已解决问题] 浏览: 229次 解决于 2018-05-16 ...
- go build报错cannot find package
go env 关键数据是这样的 GOPATH="/home/zzy/goProject" GOROOT="/usr/local/go" 项目目录是这样的 goP ...
- HTML + CSS (上)
HTML 概念: 超文本标记语言. 核心: 语义. 主体结构: <!doctype html> //告诉浏览器这是什么语言 html //主体 head //头文件 body //页面主体 ...
- 案例-2D会旋转的盒子(rotate), 会缩放的盒子(scale),动画(animation)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 第七章 yaml格式
一.简单说明 yaml是一个可读性高,用来表达数据序列的格式.YAML 的意思其实是:仍是一种标记语言,但为了强调这种语言以数据做为中心,而不是以标记语言为重点 二.基本语法 缩进时不允许使用Tab键 ...
- 升级python后yum命令出错
执行yum命令报错: yum list Loaded plugins: fastestmirror base | 3.6 kB 00:00:00 epel | 5.3 kB 00:00:00 extr ...
- vCenter 6.0 如何用client登录
使用Vmware client 输入vCenter的IP地址 然后用户名使用administrator@vsphere.local 再输入密码,即可登录vCenter了. web端也是一样,但是我遇 ...
- InnoDB global status
常见参数 Innodb_buffer_pool_pages_free 发现 Innodb_buffer_pool_pages_free 为0 ,则说明buffer_pool 已经被用光,需要增大 in ...
- 【扯淡篇】CTSC/APIO/SDOI R2时在干什么?有没有空?可以来做分母吗?
注意: 我比较弱, 并没有办法把外链bgm搞成https, 所以大家可以选择"加载不安全的脚本"或者把https改成http以获得更好的阅读体验! 据说, 退役了要写写回忆录. 但 ...