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),通过一个小东西,真真发现了自己的各方面不足.昨天发完 ...
随机推荐
- leetcode python两整数之和
# Leetcode 371 两整数之和***### 题目描述 **不使用**运算符 `+` 和 `-` ,计算两整数 `a `.`b` 之和. **示例1: ...
- 神器,阿里巴巴Java代码检查插件
背景 不久,又一气呵成发布了Eclipse/Intellij Idea下的代码检测插件PC3,可谓是国内代码优秀的检测插件.此插件检测的标准是根据<<阿里巴巴Java开发手册(终极版)&g ...
- SpringBoot传递单一参数时@RequestParam和@RequestBody的区
用SpringBoot框架做项目时,经常需要前端给后端传递参数,如果需要多条参数,通常的做法是把这些参数封装为一个对象来传递,前端用POST方式调用.但有时会遇到后端只需要一条参数(比如一个Strin ...
- su 和 su - 命令有何不同
su命令和su -命令最大的本质区别就是:前者只是切换了root身份,但Shell环境仍然是普通用户的Shell:而后者连用户和Shell环境一起切换成root身份了.只有切换了Shell环境才不会出 ...
- ZOJ-3524 拓扑排序+完全背包(好题)
题意:在一个DAG上,主角初始有W钱起点在s点,每个点有一个代价wi和价值vi,主角从起点走到某一点不能回头走,一路上可以买东西(一个点的东西可以买无限次),且体力消耗为身上负重*路径长度.主角可以在 ...
- 【JS学习】慕课网7-23编程练习 有关字符串数组
要求:1.显示打印的日期. 格式为类似“2014年03月21日 星期三” 的当前的时间.2.计算出该班级的平均分(保留整数).同学成绩数据如下:"小明:87; 小花:81; 小红:97; 小 ...
- 重新创建redis集群的注意事项
一.重新创建redis集群的注意事项 1.将每个节点下aof.rdb.nodes.conf本地备份文件删除: 2.127.0.0.1:7001> flushdb #清空当前数据库(这一步可以省略 ...
- vue 初始化rem
在assets => js => rem.js export default { init () { let sw = document.documentElement.clientWid ...
- python制作坦克对战
创建子弹类 import pygame class Bullet(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__i ...
- TreeSet集合在哪种情况下会报错
1.自然排序中的元素对象,都必须实现了Comparable接口,否则会抛出异常,案例如下: public class MySetTree { public static void main(Strin ...