PHP 匿名函数和闭包语法

PHP 匿名函数和闭包语法匿名函数 没有名字的函数 php5 3 0 新加入的语法 有两种使用匿名函数的形式 或说 匿名函数有两种存在方式 方式 1 将匿名函数赋值给一个变量 最终用的时候 非常类似 可变函数

欢迎大家来到IT世界,在知识的湖畔探索吧!

匿名函数:没有名字的函数(php5.3.0新加入的语法)

有两种使用匿名函数的形式, 或说, 匿名函数有两种存在方式:

方式1:

将匿名函数赋值给一个变量, 最终用的时候, 非常类似”可变函数”。如下:

$f1 = function () {}; //注意,这里最后有一个"分号"——必须的。

欢迎大家来到IT世界,在知识的湖畔探索吧!

上面定义该函数时,没有给名字,那就是匿名函数,并将其整体赋值给了变量$f1;

欢迎大家来到IT世界,在知识的湖畔探索吧!$f1(); //调用该匿名函数。
<?php $f1 = function(){ echo "<br/>匿名函数被调用,参数为:$p1"; }; //注意:这里最后有一个"分号"--必须的 $f1(1); //调用该匿名函数 $f1(10); //调用该匿名函数 ?>

方式2:

第二种方式的匿名函数, 基本上只作为”实参”使用。

也就是说, 有一些函数, 其实参要求是一个”函数”。

注意:能够使用匿名函数当实参用的函数, 很少很少。

这种函数系统中有这样几个:

call_user_func_array( 匿名函数, 一个数组);

//即函数call_user_func_array带2个参数,第一个参数要求是一个匿名函数,第二个要求是数组

//其作用是:将该数组的所有项,当做该匿名函数的实参传入匿名函数中并执行该匿名函数。

欢迎大家来到IT世界,在知识的湖畔探索吧!call_user_func_array( function ($p1) { echo "<br />匿名函数被调用,参数为:$p1"; } , array(100) );

输出结果:匿名函数被调用,参数为:100

匿名函数的实现

<?php $func = function() { echo "Hello, anonymous function"; } echo gettype($func); // object echo get_class($func); // Closure

原来匿名函数也只是一个普通的类而已, 也叫闭包函数(closures)

php 闭包语法 function() use ($arg) {}

php的闭包(Closure)也就是匿名函数。是PHP5.3引入的。 PHP在函数内定义的变量默认就是局部变量, PHP在变异的时候则无法确定变量是局部变量还是上层作用域内的变量,

如果需要访问上层作用域内的变量则需要使用use语句来申明, 我们可以使用use来实现类似global语句的效果。

闭包的语法很简单, 需要注意的关键字就只有use, use意思是连接闭包和外界变量。

$a = function()use($b){ }

实例:

<?php $aaa = 111; $func = function() use($aaa){ print $aaa; }; $aaa = 222; $func(); // 输出 "111" ?>

使用普通变量

<?php $arg = 'text'; $test = function () use ($arg){ var_dump($arg); }; $test(); //输出text

//再来看一下他是否可以改变外部变量

$arg = 'text'; $test = function () use ($arg){ var_dump($arg); $arg = 'text2'; }; $test(); //输出text $arg = 'text3'; $test(); //输出text ?>

所谓闭包, 就是定义一段代码, 同时对当时的运行上下文做一个快照, 并捆绑在一起, 用于在将来的某个时候让这段代码在当初的这个上下文中运行。

使用引用变量

<?php $arg = 'text'; $test = function () use (&$arg){ var_dump($arg); $arg = 'text2'; }; $test(); //输出text $arg = 'text3'; $test(); //输出text3 ?>

闭包的几个作用:

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"; //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";
};
}
$element = html ("div", "container");
echo $element(); //<div id = "container">文本测试</div>

如果是使用平时的方法, 我们会把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(fib(n-1)是找不到function的(前面没有定义fib的类型)

所以想使用闭包解除循环函数的时候就需要使用

<?php $recursive =function () use (&$recursive){ // The function is now available as $recursive }

这样的形式

4 关于延迟绑定

如果你需要延迟绑定use里面的变量, 你就需要使用引用(&), 否则在定义的时候就会做一份拷贝放到use中 //理解use(&$var)

<?php $result = 0; $one =function(){ var_dump($result); }; $two =function() use ($result) { var_dump($result); }; $three =function() use (&$result){ var_dump($result); }; $one(); // outputs NULL: $result is not in scope $two(); // outputs int(0): $result was copied $three(); // outputs int(1)

使用引用和不使用引用就代表了是调用时赋值, 还是申明时候赋值

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/89549.html

(0)
上一篇 2024年 11月 21日 上午10:05
下一篇 2024年 11月 21日 上午10:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信