php手册之匿名函数

手册目录: 语言参考---函数---匿名函数

参考详情: https://secure.php.net/manual/zh/functions.anonymous.php

评论部分:

1. by orls

当在你的匿名函数中导入变量时,只是进行简单的复制操作,而且在匿名函数定义的时候就进行了该操作,所以之后对该变量的任何修改都不会影响匿名函数,如果你需要根据变量的变化实时变化,你需要使用引用&,如下:

<?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)
?>

2. by erolmon.kskn@gmail.com

<?php
/*
(string) $name 是你想添加到类中的方法的名字.
用法 : $Foo->add(function(){},$name);
这样将会向实例中添加public方法;
*/
class Foo
{
    public function add($func,$name)
    {
        $this->{$name} = $func;
    }
    public function __call($func,$arguments){
        call_user_func_array($this->{$func}, $arguments);
    }
}
$Foo = new Foo();
$Foo->add(function(){
    echo "Hello World";
},"helloWorldFunction");
$Foo->add(function($parameterone){
    echo $parameterone;
},"exampleFunction");
$Foo->helloWorldFunction(); /*Output : Hello World*/
$Foo->exampleFunction("Hello PHP"); /*Output : Hello PHP*/
?>

3. by mike@blueroot.co.uk

当你使用匿名函数进行自我递归时, 在use()里面需要用引用操作符&,如下例:

<?php
$recursive = function () use (&$recursive){
    // The function is now available as $recursive
    static $a = 0;
    @print "$a\n";
    if($a++ == 100){
        echo 'over';
        return;
    }
    $recursive();
};

$recursive();
?>
注意,这里会产生一个fatal error:maximum function nesting level of '100' reached,这不是程序的问题,是php.ini里面有一个选项 xdebug.max_nesting_level默认设置为100,所以最高能嵌套层数必须小于100,所以如果你需要嵌套的层数大于这个数,请自行修改php.ini.同时值得一提的是,匿名函数中也可以像普通自定义函数那样使用static变量.


4. by fabiolimasouto@gmail.com

如果你将类实例的变量关联到匿名函数,那么当你使用该变量访问匿名函数时,结果也许会令你失望,如下:

<?php
$obj = new StdClass();
$obj->func = function(){
    echo "hello";
};
//$obj->func(); // 会出错,因为php会去$obj的类中寻找func()方法,结果却是undefined method
// you have to do this instead:
$func = $obj->func;
$func();

// or:
call_user_func($obj->func);

// however, you might wanna check this out:
$array['func'] = function(){
    echo "hello";
};

$array['func'](); // it works! i discovered that just recently ;)
?>

5. by reinaldorock@yahoo.com.br

rein提出一段有意思的代码,如下:

<?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
?>

注意到$fib中使用到了use(&$fib),所以当$fib改了之后会继续影响$lie的输出,如果一不小心就掉进去了,认为$lie=$fib是引用,其实不然,可以添加一层外壳进行隔绝保护:

<?php
$fib
= call_user_func(function(){
  
   
$fib = function($n) use(&$fib) {
        if(
$n == 0 || $n == 1) return 1;
        return
$fib($n - 1) + $fib($n - 2);
    };
    return
$fib;
});

echo
$fib(2) . "\n";//2
$ok = $fib;

$fib = function(){die('error')};//rewrite $fib variable but don't referenced $fib used by closure
echo $ok(5);//result ok
?>

使用call_user_func之后,里面的$fib与外面的$fib的作用域范围就不一样了,对外部的$fib的修改将不会影响内部对$fib的引用,也不会对$lie造成任何影响,测试这段代码的时候我没有注意到&$fib导致以为匿名函数的赋值是引用行为,结果发现修改$lie后并不会对$fib造成影响,当即就崩了,还专门跑去看php内核匿名的实现,发现其是通过closure类和__invoke来实现的,并不会造成这样的结果,然后一字一字排查,才发现这个愚蠢的疏忽.


6. by andris@codeaid.net

你可以在类内使用匿名函数对private或者protected变量进行读写,在匿名函数中可以直接使用$this,不需要使用use($this)将$this传入进去,这样反而会发生error,如下:

<?php
class Scope
{
    protected $property = 'default';
    // or even
    // private $property = 'default';

    public function run()
    {
        $func = function() {
            $this->property = 'changed';
        };
        $func();
        var_dump($this->property);
    }
}

$scope = new Scope();
$scope->run();
?>
输出'changed'


如有任何错误,请及时联系并改正(所有PHP代码的运行环境为PHP7)!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值