PHP的学习--PHP的闭包
php的闭包(Closure)也就是匿名函数,是PHP5.3引入的。
闭包的语法很简单,需要注意的关键字就只有use,use是连接闭包和外界变量。
$a = function() use($b) {}
简单例子如下:
function callback($fun) { $fun(); } $msg = "Hello, everyone"; $fun = function () use($msg) { print "This is a closure use string value, msg is: $msg. <br />/n"; }; $msg = "Hello, everybody"; callback($fun);
结果是:This is a closure use string value, msg is: Hello, everyone. <br />/n
在PHP新开放的闭包语法中, 我们用use来使用闭包外部定义的变量的。这里我们使用了外部变量$msg,定义完之后,又对其值进行了改变,闭包被执行后输出的是原始值。以传值方式传递的基础类型参数,闭包use的值在闭包创建是就确定了。
小应用如下:
/** * 一个利用闭包的计数器产生器 * 这里其实借鉴的是python中介绍闭包时的例子... * 我们可以这样考虑: * 1. counter函数每次调用, 创建一个局部变量$counter, 初始化为1. * 2. 然后创建一个闭包, 闭包产生了对局部变量$counter的引用. * 3. 函数counter返回创建的闭包, 并销毁局部变量, 但此时有闭包对$counter的引用, * 它并不会被回收, 因此, 我们可以这样理解, 被函数counter返回的闭包, 携带了一个游离态的 * 变量. * 4. 由于每次调用counter都会创建独立的$counter和闭包, 因此返回的闭包相互之间是独立的. * 5. 执行被返回的闭包, 对其携带的游离态变量自增并返回, 得到的就是一个计数器. * 结论: 此函数可以用来生成相互独立的计数器. */ function counter() { $counter = 1; return function() use(&$counter) {return $counter ++;}; } $counter1 = counter(); $counter2 = counter(); echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; ?>
闭包的作用
1. 减少foreach的循环的代码
比如手册http://php.net/manual/en/functions.anonymous.php 中的例子Cart
<?php // 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。 // 其中有一个方法用来计算购物车中所有商品的总价格。该方法使用了一个closure作为回调函数。 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);// 打出出总价格,其中有 5% 的销售税. print $my_cart->getTotal(0.05) . "\n"; // The result is 54.29 ?>
这里如果我们改造getTotal函数必然要使用到foreach。
2. 减少函数的参数
function html($code , $id="", $class=""){ if ($id !== "") $id = " id = \"$id\"" ; $class = ($class !== "")? " class =\"$class\">":">"; $open = "<$code$id$class"; $close = "</$code>"; return function ($inner = "") use ($open, $close){ return "$open$inner$close";}; }
如果是使用平时的方法,我们会把inner放到html函数参数中,这样不管是代码阅读还是使用都不如使用闭包。
3. 解除递归函数
<?php $fib = function($n) use(&$fib) {if($n == 0 || $n == 1) return 1;return $fib($n - 1) + $fib($n - 2); };echo $fib(2) . "\n"; // 2 $lie = $fib; $fib = function(){die('error');};//rewrite $fib variable echo $lie(5); // error because $fib is referenced by closure
注意上题中的use使用了&,这里不使用&会出现错误fib(n-1)是找不到function的(前面没有定义fib的类型)
所以想使用闭包解除循环函数的时候就需要使用
<?php $recursive = function () use (&$recursive){ // The function is now available as $recursive }
这样的形式。
4. 延迟绑定
如果你需要延迟绑定use里面的变量,你就需要使用引用,否则在定义的时候就会做一份拷贝放到use中
<?php $result = 0;$one = function() {var_dump($result); };$two = function() use ($result) {var_dump($result); };$three = function() use (&$result) {var_dump($result); };$result++;$one(); // outputs NULL: $result is not in scope $two(); // outputs int(0): $result was copied $three(); // outputs int(1)
使用引用和不使用引用就代表了是调用时赋值,还是申明时候赋值
转载于:https://www.cnblogs.com/CraryPrimitiveMan/p/4129285.html
PHP的学习--PHP的闭包相关推荐
- sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map)
sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map) 这几天学习和查看了jQuery和Property这两个很流行的前端库的御用选择器组件Sizzle.js的源代码,收获还是相对多的!之 ...
- Python学习笔记:闭包与作用域
文章目录 零.学习目标 一.闭包(Enclosure) (一)函数引用 1.引用变量 2.引用函数 (二)闭包为何物 1.闭包概述 2.闭包满足三个条件 3.案例演示闭包 二.命名空间(Namespa ...
- lua学习笔记之闭包
Lua中的函数是具有适当词法范围的一级值. lua作为一级值意味着函数与数字和字符串一样具有值,可以将函数存储在变量或者表中,将函数作为参数传递给其它函数,也可以作为结果返回函数. lua具有词法范围 ...
- 初探swift语言的学习笔记三(闭包-匿名函数)
作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29353019 转载请注明出处 如果觉得文章对你有所帮助,请通过留言 ...
- Python学习笔记: 闭包
闭包的基本定义 在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数.这个被引用的自由变 ...
- golang学习之四:闭包、defer
golang闭包.defer 闭包 闭包以引用的方式捕捉外部变量 闭包变量与作用域 传统函数局部变量 闭包的变量 defer 延迟:在函数执行完毕之前调用 多个defer执行顺序 闭包 闭包以引用的方 ...
- Swift学习(八):闭包(闭包表达式,尾随闭包,闭包的定义,自动闭包)
闭包表达式(Closure Expression) 可以通过func定义一个函数,也可以通过闭包表达式定义一个函数 func函数 闭包定义函数 闭包表达式调用可以直接省略参数名 闭包定义函数也可以写为 ...
- wift学习笔记之闭包
根据上一节的例子,我们讲解此次闭包的编写 上节例子: [格式] {(参数名称:参数类型)->返回类型 in 闭包函数体} [举例] [闭包函数简化] 1.由于AutoAdd函数中addFunc这 ...
- javascript中重要概念-闭包-深入理解
在上次的分享中javascript--函数参数与闭包--详解,对闭包的解释不够深入.本人经过一段时间的学习,对闭包的概念又有了新的理解.于是便把学习的过程整理成文章,一是为了加深自己闭包的理解,二是给 ...
最新文章
- MSSQL-SQL SERVER 分页原理
- TMG学习(四),允许内部网络解析本地主机的Netbiso名称
- 5月28日任务 Apache和PHP结合、Apache默认虚拟主机
- drupal7 的安装方法
- Vision GUI programming products
- 大数据可视化方法有哪些
- 一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目
- 爬虫代理IP产品如何选择
- Python程序设计基础(第九章 字典和集合 练习记录)
- torch.cuda.amp.GradScaler(enabled=CFG.apex)是什么意思?
- 数字时代的“文艺复兴”?起底数字藏品,让人欢喜让人愁
- centos7设置开机为命令行启动
- 在校大学生学业预警系统java_关于学业预警系统上线使用的通知
- 一文搞懂0.1UF和10UF电容并联使用技巧
- 未来5年做好随时失业的准备
- HTML保存变暗了怎么办,浮漂用久了漂尾变暗怎么办?试试这样做,没准还有救...
- Time New Roman字体
- TP6(thinkphp6)队列与延时队列
- ADAMS 文件导入的相关研究
- 关于asm(” RPT #N || NOP”)