• 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的不同以外,其他的都是可以的,比如可以作为函数的返回值等等的内容。

  • 相关阅读:
    Unity c# 状态机的简单入门
    python实战教程之自动扫雷(自己存下来学习之用)
    Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress-十一(1)
    Ubuntu安装eclipse以及创建快捷方式
    Dockerfile-HEALTHCHECK指令
    各个版本Microsoft Visual C++运行库下载
    docker 远程连接设置
    centos7安装redis3.2.12
    Windows下允许redis远程访问
    UltraISO制作U盘启动盘-centos7
  • 原文地址:https://www.cnblogs.com/XGHeaven/p/4245306.html
Copyright © 2020-2023  润新知