zoukankan      html  css  js  c++  java
  • PHP 闭包获取外部变量和global关键字声明变量的区别

    最近在学习workerman的时候比较频繁的接触到回调函数,使用中经常会因为worker的使用方式不同,会用这两种不同的方式去调用外部的worker变量,这里就整理一下PHP闭包获取外部变量和global关键字声明变量的区别。

    闭包

    闭包是一个常见的概念,我们通常可以将其与回调函数配合使用,可以使代码更加简洁易读。
    闭包可以通过拷贝的方式让函数使用父作用域中的变量。如:

    $global = 'hello';
    
    $bbb = function()use($global){
    	echo $global."
    ";
    };
    $bbb();
    //输出 'hello'
    

    global关键字声明变量

    通过global声明变量同样可以使函数体调用到函数外部的变量,不过global与use不同,globle关键字会使创建一个与外部变量同名的引用,并且在函数内对变量作出修改同样会作用域外部变量。

    $global = 'hello';
    $fun = function(){
    	global $global;
    	$global =' world';
    	echo $global."
    ";
    };
    $fun();
    // 输出 'world'
    

    这里只是创建一个同名引用而已,并不会改变原本外部变量$global的作用域,也就是说在另外一个函数中调用该依旧需要声明或者使用闭包

    $global = 'hello';
    $fun = function(){
    	global $global;
    	$global =' world';
    	echo 'a:'.$global."
    ";
    };
    
    $ccc = function(){
    	echo 'b:'.$global;
    };
    $fun()
    $ccc()
    
    /*
    输出
    a: world
    
    Notice: Undefined variable: global in xxxxxxx on line xx
    */
    
    

    再稍微改一下代码,这样更容易对比闭包和global关键字声明变量这两种访问外部变量方式的区别。

    <?php
    $global = 'hello';
    $fun = function(){
    	global $global;
    	$global ='world';
    	echo 'a:'.$global."
    ";
    };
    
    $bbb = function()use($global){
    	$global = 'china';
    	echo 'c:'.$global."
    ";
    };
    
    $fun();
    
    echo 'b:'.$global."
    ";
    $bbb();
    echo 'd:'.$global;
    

    这里b和d两个输出可以看出来,global改变了外部变量的值,而闭包方式并没有。

    输出:

    a: world
    b: world
    c:china
    d: world
    
    

    最后再贴一个官方文档中比较经典的使用匿名函数,闭包与回调函数配合的例子:

    class Cart
    {
        const PRICE_BUTTER  = 1.00;
        const PRICE_MILK    = 3.00;
        const PRICE_EGGS    = 6.95;
    
        protected   $products = array();
    
        public function add($product, $quantity)
        {
            $this->products[$product] = $quantity;
        }
    
        public function getQuantity($product)
        {
            return isset($this->products[$product]) ? $this->products[$product] :
                FALSE;
        }
    
        public function getTotal($tax)
        {
            $total = 0.00;
    
            $callback =
                function ($quantity, $product) use ($tax, &$total)
                {
                    $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                        strtoupper($product));
                    $total += ($pricePerItem * $quantity) * ($tax + 1.0);
                };
            array_walk($this->products, $callback);
            return round($total, 2);
        }
    }
    
    $my_cart = new Cart;
    
    $my_cart->add('butter', 1);
    $my_cart->add('milk', 3);
    $my_cart->add('eggs', 6);
    
    
    print $my_cart->getTotal(0.05) . "
    ";
    
    
  • 相关阅读:
    Java 8实战之读书笔记五:超越Java 8
    Quartz的简单使用
    Quartz实现数据库动态配置定时任务
    Java解析Groovy和Shell的代码
    Spring学习笔记(3)——快速入门
    linux的防火墙端口配置
    气泡提示 纯CSS
    解决LINUX下SQLPLUS时上下左右键乱码问题
    redhat Enterprise Linux 6 VNC安装
    使用mount命令挂载CDROM
  • 原文地址:https://www.cnblogs.com/augurG/p/7955439.html
Copyright © 2011-2022 走看看