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的闭包相关推荐

  1. sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map)

    sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map) 这几天学习和查看了jQuery和Property这两个很流行的前端库的御用选择器组件Sizzle.js的源代码,收获还是相对多的!之 ...

  2. Python学习笔记:闭包与作用域

    文章目录 零.学习目标 一.闭包(Enclosure) (一)函数引用 1.引用变量 2.引用函数 (二)闭包为何物 1.闭包概述 2.闭包满足三个条件 3.案例演示闭包 二.命名空间(Namespa ...

  3. lua学习笔记之闭包

    Lua中的函数是具有适当词法范围的一级值. lua作为一级值意味着函数与数字和字符串一样具有值,可以将函数存储在变量或者表中,将函数作为参数传递给其它函数,也可以作为结果返回函数. lua具有词法范围 ...

  4. 初探swift语言的学习笔记三(闭包-匿名函数)

    作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29353019 转载请注明出处 如果觉得文章对你有所帮助,请通过留言 ...

  5. Python学习笔记: 闭包

    闭包的基本定义 在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数.这个被引用的自由变 ...

  6. golang学习之四:闭包、defer

    golang闭包.defer 闭包 闭包以引用的方式捕捉外部变量 闭包变量与作用域 传统函数局部变量 闭包的变量 defer 延迟:在函数执行完毕之前调用 多个defer执行顺序 闭包 闭包以引用的方 ...

  7. Swift学习(八):闭包(闭包表达式,尾随闭包,闭包的定义,自动闭包)

    闭包表达式(Closure Expression) 可以通过func定义一个函数,也可以通过闭包表达式定义一个函数 func函数 闭包定义函数 闭包表达式调用可以直接省略参数名 闭包定义函数也可以写为 ...

  8. wift学习笔记之闭包

    根据上一节的例子,我们讲解此次闭包的编写 上节例子: [格式] {(参数名称:参数类型)->返回类型 in 闭包函数体} [举例] [闭包函数简化] 1.由于AutoAdd函数中addFunc这 ...

  9. javascript中重要概念-闭包-深入理解

    在上次的分享中javascript--函数参数与闭包--详解,对闭包的解释不够深入.本人经过一段时间的学习,对闭包的概念又有了新的理解.于是便把学习的过程整理成文章,一是为了加深自己闭包的理解,二是给 ...

最新文章

  1. MSSQL-SQL SERVER 分页原理
  2. TMG学习(四),允许内部网络解析本地主机的Netbiso名称
  3. 5月28日任务 Apache和PHP结合、Apache默认虚拟主机
  4. drupal7 的安装方法
  5. Vision GUI programming products
  6. 大数据可视化方法有哪些
  7. 一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目
  8. 爬虫代理IP产品如何选择
  9. Python程序设计基础(第九章 字典和集合 练习记录)
  10. torch.cuda.amp.GradScaler(enabled=CFG.apex)是什么意思?
  11. 数字时代的“文艺复兴”?起底数字藏品,让人欢喜让人愁
  12. centos7设置开机为命令行启动
  13. 在校大学生学业预警系统java_关于学业预警系统上线使用的通知
  14. 一文搞懂0.1UF和10UF电容并联使用技巧
  15. 未来5年做好随时失业的准备
  16. HTML保存变暗了怎么办,浮漂用久了漂尾变暗怎么办?试试这样做,没准还有救...
  17. Time New Roman字体
  18. TP6(thinkphp6)队列与延时队列
  19. ADAMS 文件导入的相关研究
  20. 关于asm(” RPT #N || NOP”)

热门文章

  1. 硬件知识:电脑组装机必备的知识梳理
  2. 数据迁移,不停机上线的正确姿势
  3. 你知道为啥程序员下班后只关显示器从不关电脑?
  4. 盘点神奇却少为人知的IntelliJ IDEA快捷键
  5. Linux中shell变量作用域笔记
  6. 扎心!程序员泪奔的8个瞬间
  7. 浅说 XSS和CSRF
  8. JavaScript的一些常用方法
  9. 学会拐弯,才是人生大智慧(深度好文)
  10. python正则去除换行符,关于python:用于删除换行符的正则表达式