PHP 闭包获取外部变量和global关键字声明变量的区别
最近在学习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关键字声明变量的区别的更多相关文章
- 【python】为什么修改全局的dict变量不用global关键字
转自:http://my.oschina.net/leejun2005/blog/145911?fromerr=qnPCgI19#OSC_h4_8 为什么修改字典d的值不用global关键字先声明呢? ...
- ES5-ES6-ES7_let关键字声明变量
let命令的介绍 let是ECMAScript6中新增的关键字,用于声明变量.它的用法类似于var var a = 3 let b = 4 let变量的声明 let 命令的特点不允许在同一作用域下声明 ...
- C++ —— 类中static和const关键字声明变量的初始化方式总结
在类中声明变量/常量时,经常会用到static.const关键字.对于该变/常量的初始化问题,网上有许多相关文章,但是大多不够完善,或者存在错误.经过实际验证,总结如下: (注明:测试编译平台为VS2 ...
- javascript的var声明变量和不用var声明变量在全局作用域的区别;
在全局作用域下,使用var定义的变量不可以delete,没有var 定义的变量可以delete.也就说明隐含全局变量严格来说不是真正的变量,而是全局对象的属性,因为属性可以通过delete删除,而变量 ...
- Java如何声明变量?JS如何声明变量?
Java采用强类型变量检查,像C语言一样.所有变量在编译之前必须声明,而且不能使用没有赋值的变量.例如:int x;x=1234;char y='F';其中X=1234说明是一个整数,Y='F'说明是 ...
- 全局变量和局部变量(global关键字)
1.定义在函数外部的就是全局变量,它的作用域从定义处一直到文件结尾. 2.函数内定义的变量就是局部变量,它的作用域为函数定义范围内. 3.函数之间存在作用域互不影响. 4.函数内访问全局变量需要 gl ...
- Java(2)详解注释&关键字&常量&变量&标识符
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201497.html 博客主页:https://www.cnblogs.com/testero ...
- js声明变量的三种方式及作用域
js声明变量的三种方式及作用域 CreateTime--2017年9月11日17:19:11 Author:Marydon 一.参考链接 本篇文章的创作灵感来源于博主-奔跑的铃铛关于js中cons ...
- js声明变量的三种方式
JS 声明变量的三种方式 (1)使用变量步骤:a.声明-->b.赋值-->3.调用 正确用法: <script type="text/javascript"> ...
随机推荐
- C#异步编程のawait和async关键字来写异步程序
一.await和async关键字 .Net平台不断推出了新的异步编程模型,在.net4.5中加入了关键字await和async,顾名思义,await是指方法执行可等待,即可挂起直到有结果(不是必须立即 ...
- sql截取日期/时间的单独部分,比如年、月、日、小时、分钟等等
可以使用EXTRACT() 函数.(oracle和mysql都有该函数) 语法: EXTRACT(unit FROM date) date 参数是合法的日期表达式.unit 参数可以是下列的值:YEA ...
- WebSocket原理与实践(二)---WebSocket协议
WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...
- nginx-1.13.12 源码配置清单
configure命令支持以下参数: --help打印帮助信息. --prefix=安装路径定义一个将保留服务器文件的目录.这个相同的目录也将被用于由configure(由库源创建的路径除外)和ngi ...
- C++ 预处理器
直接上代码 1.#define 预处理 #include <iostream> using namespace std; #define PI 3.14159 int main () { ...
- 通过socket获取图片并保存
网络操作的相关API gethostbyname/gethostbyaddr/getservbyname struct hostent *gethostbyname(const char *name) ...
- odoo 学习
1.2.3.41.2.5.62.410.6变成1.234,1.256,2.4,10.6 def get_bom_namenum(self, cr, uid, ids, field_name, arg, ...
- Python基础语法复习
1.数据类型 List 列表 函数 append(): 在列表末尾追加. count(): 计算对象在列表中出现的次数. extend():将列表内容添加到列表中. index(): 计算对象在列表中 ...
- b/s程序真的很方便部署吗
公共应用当然是web系统,这个不说,我说的是企业应用. 最近一些年在企业开发中都提倡web应用,仿佛winform可以结束了,但真的这样吗?最近几天的真实经历如下: 我们部门新开发了一套系统要上线,由 ...
- 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)
编者按:这篇文章来自简书的一个位博主Jeffbond,读了好几遍,翻译的质量比较高,原文链接:分布式一致性算法:Raft 算法(Raft 论文翻译),版权一切归原译者. 同时,第6部分的集群成员变更读 ...