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)

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

时间: 2024-10-06 16:01:50

PHP的学习--PHP的闭包的相关文章

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

sizzle.js学习笔记利用闭包模拟实现数据结构:字典(Map) 这几天学习和查看了jQuery和Property这两个很流行的前端库的御用选择器组件Sizzle.js的源代码,收获还是相对多的!之前一直做使用Java语言开发,其丰富的组件类库使得开发效率那叫一个快呀!突然转来做JavaScript一时间还有点儿不适应(快半年了),不过自从看见那么多漂亮的网站和对JavaScript接触的越来越多,也发现了其中的一些乐趣.正如自己一直坚信的那样,编程语言仅仅是工具,重要的是编程思想!使用Jav

学习总结 javascript 闭包

学习地址 :http://stackoverflow.com/questions/111102/how-do-javascript-closures-work 1,关于闭包的简单实现 //example 1 function sayHello(name) { var words = "hello," + name; var sayForAlert = function () { alert(words); } sayForAlert(); } //sayHello("jack

JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象

目录 一.闭包(Closure) 1.1.闭包相关的问题 1.2.理解闭包 二.对象 2.1.对象常量(字面量) 2.2.取值 2.3.枚举(遍历) 2.4.更新与添加 2.5.对象的原型 2.6.删除 2.7.封装 三.函数 3.1.参数对象 (arguments) 3.2.构造函数 3.3.函数调用 3.3.1.call 3.3.2.apply 3.3.3.caller 3.3.4.Callee 3.5.立即执行函数表达式 (IIFE) 3.5.1.匿名函数与匿名对象 3.5.2.函数与函数

avaScript学习总结(二)——闭包、IIFE、apply、函数与对象 目录

一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div,for循环绑定事件. 示例代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> <style type="

每天学习一点Scala06_闭包

一个函数字面量的函数体通常只能使用输入参数和函数字面量内定义的本地变量.不过,Scala允许一个函数字面量使用它所在环境的变量. 所谓"闭包",指的是这样的一个函数字面量,它使用一个从其所在环境"捕获"到的非本地.非参数变量.有时人们会交替使用术语"函数字面量"和"闭包".但是从技术上来说,它们并不相同. 下面是一个闭包的例子: def encodeWithSeed(num:Int, seed:Int):Long = {   

Swift学习(2函数闭包)

函数的定义 1.函数的基础写法 func 函数名(形参列表)->返回值类型 例: func sum(x:int ,y:int) -> int{ return x+y } print(sun(x:10,y:50)) 2.外部参数的使用,就是在形参前加一个名字,外部参数不会影响函数内部细节,外部参数会让外部调用看起来更加的直观 例:func sum(num1 x:int ,num2 y:int )-> int{ return x+y } print(sum(num1:30,num2:40))

Javascript学习笔记:闭包题解(3)

代码: 1 function assignHandler(){ 2 var element=document.getElementById('someElementId'); 3 4 element.onclick=function(){ 5 alert(element.id); 6 } 7 } 问题:请问以上代码是否存在内存泄漏? 正确答案:存在内存泄漏 解析:由于上段代码中存在闭包,闭包会保存包含该闭包的函数的作用域链,因此element对象会一直存在于内存中,不会被垃圾回收机制回收掉.那么

【前端学习笔记】闭包的作用及案例

1.保存函数执行状态: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="father"> <p>保存函数执行状态</p> <p>性能

scala学习手记30 - 闭包

首先要弄白闭包的概念. 教材中的说法是:闭包是一种特殊的函数值,闭包中封闭或绑定了在另一个作用域或上下文中定义的变量.这里说闭包是一种特殊的函数值. 维基百科中的说法是:在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体.闭包在运行时可以