前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php (匿名函数和闭包)

php (匿名函数和闭包)

作者头像
双面人
发布2020-04-03 17:47:25
1.1K0
发布2020-04-03 17:47:25
举报
文章被收录于专栏:热爱IT热爱IT

 一、什么是闭包

1、闭包和匿名函数在php5.3.0中两个php新特性,使用的也最多,这两个特性听起来很吓人, 其实很容易理解,这两个特性非常有用,每个php开发者都应该掌握。

2、闭包是指在创建时封装周围状态的函数,即便闭包所在的环境不存在了,闭包中封装的状态依然存在,这个概念很难理解 不过一单掌握了,将会对你的生活带来巨大的变化。

3、匿名函数其实就是没有名称的函数,匿名函数可以赋值给变量,还能像其他任何php对象那样传递,不过匿名函数仍然是 匿名函数,因此可以调用,还可以传入参数,匿名函数特别适合作为函数或方法的回调。 理论上讲,闭包和匿名函数是不同的概念,不过,php将其视作相同的概念,所以,我提到闭包时,指的也是匿名函数, 反之亦然。

4、php闭包和匿名函数使用的句法和普通函数相同,不过别被这一点迷惑了,闭包和匿名函数其实是伪装成函数的对象, 如果审查php闭包和匿名函数,会发现他们是Closure类的实例,闭包和字符串或整数一样,也是一等值类型。  

二、创建一个闭包

$closure = function ($name) {     return sprintf('Hello %s', $name); }; echo $closure('Yee Jason');  输出 Hello Yee Jason.

之所以能调用$closure变量,是因为这个变量的值是一个闭包,而且闭包对象实现了 __invoke()魔术方法,只要 变量名后面有 (),php就会查并调用__invoke() 方法。 

我通常把闭包当做函数和方法的回调使用,很多php函数都会用到回调函数,例如 array_map和preg_replace_callback() 是使用匿名函数的绝佳时机,记住,闭包和其他值一样,可以作为参数传入其他php函数。

$numberPlusOne = array_map(function($number) {     return $number + 1; }, [1, 2, 3]); print_r($numberPlusOne); 在PHP闭包之前, php开发者无法选择,只能单独创建具名函数,然后引用那个函数,这么做,代码执行的稍微慢一点, 而且把回调的实现和使用场所隔离开了,传统的php代码:

function incrementNumber($number) {     return $number + 1; } $numberPlusOne = array_map('incrementNumber', [1, 2, 3]); print_r($numberPlusOne);   以上两个例子输出:Array ( [0] => 2 [1] => 3 [2] => 4 )

三、附加状态 前面演示了如何把匿名函数当成回调使用,下面探讨如何为php闭包附加并封装状态,javascript开发者 可能对php的闭包感到奇怪,因为php闭包不会像真正的javascript闭包那样自动封装应用的状态,在php中, 必须手动调用闭包对象的bindTo()方法或者使用use 关键字,把状态附加到php闭包上。 使用 use 关键字附加闭包状态常见的多,因此我们先看这种方式,使用use 关键字把变量附加到闭包上时, 附加的变量会记住附件时付给他的值。 function enclosePerson($name) {     return function ($doCommand) use ($name) {         return sprintf('%s, %s', $name, $doCommand);     }; } $clay = enclosePerson('Clay'); echo $clay('get me sweet tea!');  以上代码输出:Clay get me sweet tea 

 使用use关键字,把多个参数传入闭包时,需要还是用,号分隔开。

 具名函数enclosePerson() 有个名为$name的参数,这个函数返回一个闭包对象,而且这个闭包对象封装了 $name参数,  即便 返回的闭包对象跳出了 enclosePerson() 函数的作用域,它也会记住$name参数的值,因为$name变量仍在闭包中。

 使用bindTo方法附加闭包的状态

别忘了php 闭包是对象,与任何其他的php对象类似,每个闭包实例都可以使用$this关键字获取闭包的内部状态。 闭包对象的默认状态没什么用,不过有一个 __invoke()魔术方法和bindTo() 方法,仅此而已。 但是bindTo() 方法为闭包增加了一些有趣的潜力,我们可以使用这个方法把Closure对象的内部状态绑定到其他的对象上, bindTo() 方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的php类,因此闭包可以访问绑定闭包的对象中 受保护和私有的成员变量。 你会发现,php框架经常使用bindTo()方法把路由URL映射到匿名回调函数上,框架会把匿名函数绑定到应用对象上, 这么做可以在这个匿名函数中使用 $this关键字引用重要的对象。 例子: class APP {     protected $routes = array();     protected $responseStatus = '200 ok';     protected $responseContentType = 'text/html';     protected $responseBody = 'hello world';     public function addRoute($routePath, $routeCallback)     {         $this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__);     }     public function dispath($currentPath)     {         foreach ($this->routes as $routePath => $callback) {             if ($routePath == $currentPath) {                 $callback();             }         }         header('HTTP/1.1'. $this->responseStatus);         header('Content-type' . $this->responseContentType);         header('Content-length' . $this->responseBody);         echo $this->responseBody;     } } 我们要特别注意addRoute方法,这个方法的参数分别是一个路由路径和路由回调,dispatch() 方法的参数是当前的HTTP请 求的  路径,它会调用匹配的路由回调,我们把路由绑定到当前的App实例上,这么做就能再回调函数中处理App实例的状态 。

$app = new App(); $app->addRoute('/users/josh', function () {     $this->responseContentType = 'application/json; charset=utf8';     $this->responseBody = '{"name" : "yee Jason"}'; }); $app->dispatch('/users/josh');

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档