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

闭包

闭包是一个常见的概念,我们通常可以将其与回调函数配合使用,可以使代码更加简洁易读。

闭包可以通过拷贝的方式让函数使用父作用域中的变量。如:

$global = 'hello';

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

global关键字声明变量

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

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

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

$global = 'hello';
$fun = function(){
global $global;
$global =' world';
echo 'a:'.$global."\n";
}; $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."\n";
}; $bbb = function()use($global){
$global = 'china';
echo 'c:'.$global."\n";
}; $fun(); echo 'b:'.$global."\n";
$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) . "\n";

PHP 闭包获取外部变量和global关键字声明变量的区别的更多相关文章

  1. 【python】为什么修改全局的dict变量不用global关键字

    转自:http://my.oschina.net/leejun2005/blog/145911?fromerr=qnPCgI19#OSC_h4_8 为什么修改字典d的值不用global关键字先声明呢? ...

  2. ES5-ES6-ES7_let关键字声明变量

    let命令的介绍 let是ECMAScript6中新增的关键字,用于声明变量.它的用法类似于var var a = 3 let b = 4 let变量的声明 let 命令的特点不允许在同一作用域下声明 ...

  3. C++ —— 类中static和const关键字声明变量的初始化方式总结

    在类中声明变量/常量时,经常会用到static.const关键字.对于该变/常量的初始化问题,网上有许多相关文章,但是大多不够完善,或者存在错误.经过实际验证,总结如下: (注明:测试编译平台为VS2 ...

  4. javascript的var声明变量和不用var声明变量在全局作用域的区别;

    在全局作用域下,使用var定义的变量不可以delete,没有var 定义的变量可以delete.也就说明隐含全局变量严格来说不是真正的变量,而是全局对象的属性,因为属性可以通过delete删除,而变量 ...

  5. Java如何声明变量?JS如何声明变量?

    Java采用强类型变量检查,像C语言一样.所有变量在编译之前必须声明,而且不能使用没有赋值的变量.例如:int x;x=1234;char y='F';其中X=1234说明是一个整数,Y='F'说明是 ...

  6. 全局变量和局部变量(global关键字)

    1.定义在函数外部的就是全局变量,它的作用域从定义处一直到文件结尾. 2.函数内定义的变量就是局部变量,它的作用域为函数定义范围内. 3.函数之间存在作用域互不影响. 4.函数内访问全局变量需要 gl ...

  7. Java(2)详解注释&关键字&常量&变量&标识符

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201497.html 博客主页:https://www.cnblogs.com/testero ...

  8. js声明变量的三种方式及作用域

      js声明变量的三种方式及作用域 CreateTime--2017年9月11日17:19:11 Author:Marydon 一.参考链接 本篇文章的创作灵感来源于博主-奔跑的铃铛关于js中cons ...

  9. js声明变量的三种方式

    JS 声明变量的三种方式 (1)使用变量步骤:a.声明-->b.赋值-->3.调用 正确用法: <script type="text/javascript"> ...

随机推荐

  1. JS实现奇偶数的判断

    <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>标题页-学无忧(www.x ...

  2. WPFのGrid布局的深度理解

    以下以row定义说明问题,列类似: <Grid>        <Grid.RowDefinitions>            <RowDefinition /> ...

  3. django知识点回顾(上)

    Django---知识点: 1. 配置文件: media: avatar = models.FileField(upload_to='avatar')#数据库里的model MEDIA_ROOT=os ...

  4. [NOIP2018]保卫王国

    嘟嘟嘟 由于一些知道的人所知道的,不知道的人所不知道的原因,我来发NOIP2018day2T3的题解了. (好像我只是个搬运工--) 这题真可以叫做NOIplus了,跟其他几道比较水的题果然不一样,无 ...

  5. UCML异常提示:无效URI

    UCML异常提示界面,点击确定后UCML退出无法使用,原因见图二 图一: 图二:源码路径错误导致找不到路径出异常提示,在数据库中将数据update回正确路径即可解决该问题

  6. 如何优雅地使用Sublime Text3(转)

    转自http://www.jianshu.com/p/3cb5c6f2421c/ Sublime Text:一款具有代码高亮.语法提示.自动完成且反应快速的编辑器软件,不仅具有华丽的界面,还支持插件扩 ...

  7. 解决VC++6.0打开文件或添加文件到工程出错的问题

    相信很多朋友在安装VC++6.0之后,发现无法使用打开文件命令.同时,打开了工程,却无法实现文件添加到工程的问题.一旦进行如此操作,便会出现应用程序错误,需要关闭应用程序.为此,不胜其烦.更有甚者,以 ...

  8. MATLAB的两种移位运算

    MATLAB的两种移位运算: 1)circshift矩阵移位 circshift:循环移位数组 语法:B = circshift(A,shiftize) 说明: B  = circshift(A,sh ...

  9. 开源项目Bug悬赏任务

    导读 2014 年开源加密库 OpenSSL 项目爆出的高危漏洞 Heartblood 让世人意识到一些鲜为人知的开源项目对整个互联网和其它基础设施的完整性和可靠性至关重要,随后 Linux 基金会发 ...

  10. Android学习之APP点击功能闪退问题的处理一

    java代码如下: activity_main.xml代码如下: APP测试问题:安装好APP后,点击“点击事件”,APP会闪退 检查方向: 1.查看java代码中的成员变量textview是否初始化 ...