Loading... # [谈谈PHP中的匿名函数与闭包](https://blog.p2hp.com/archives/7272) ```php <?php //匿名函数,说白了就是“没有名字的函数”,不多说。给一段代码可能更为明白: //例一,定义匿名函数并调用 $str='world'; $func=function ($str) { echo 'hello '.$str; }; $func($str);// 输出 hello world //例二,定义匿名函数,用use 引入变量并调用 $str='world'; $func=function () use ($str) { echo 'hello '.$str; }; $func();//输出 hello world //例三 //在函数中把匿名函数返回,并且调用它 function getPrintStrFunc() { $func = function ($str) { echo $str; }; return $func; } $printStrFunc = getPrintStrFunc(); $printStrFunc('some string'); // 例四 //把匿名函数当做参数传递,并且调用它,这里实现了先定义参数 ,再传入函数的效果(和普通的函数先定义函数,再传入参数调用相反) function callFunc($func) { $func('some string'); } $printStrFunc = function ($str) { echo $str; }; callFunc($printStrFunc); //也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉 callFunc(function ($str) { echo $str; }); // 匿名函数和普通函数最大的区别是在于,匿名函数可以作为一个具体的“值”赋予给变量或者对象属性,其次,由于匿名函数可以被定义在不同地方,使得他可以有效利用他所在的局域内的变量(或者说上下文中的变量)。下面例子中就是这样一种情况。 class foo { public function exec(Closure $callback) { echo $callback(); } } $name = 'nick'; (new foo)->exec(function () use ($name) { return 'hi, '. $name; }); // 输出: hi, nick // 我们可以看到,匿名函数使用了上下文中的变量$name。而实际上,这个匿名函数是在另一个地方被执行(是在foo类里面被执行的)。这样使得我们不必将变量name的值通过参数传递到类foo的exec方法中,而且可以减少在exec方法中不必要的处理逻辑,使得类更容易专注于自己的职责。 // 匿名函数的作用还有很多,要知道,函数定义的时候是不会执行的,除非被调用。上文中例子其实就是这样,我们可以看到,例子中,对$name变量的处理是在方法exec被调用后才发生,且利用了匿名函数被定义时的上下文中的变量。这种特性,我们可以利用来实现一个控制反转(IoC)容器。 /** * 一个简单的IoC容器 */ class Container { protected static $bindings; public static function bind($abstract, Closure $concrete) { static::$bindings[$abstract] = $concrete; } public static function make($abstract) { return call_user_func(static::$bindings[$abstract]); } } /** * 示例用的 talk 类 */ class talk { public function greet($target) { echo 'hi, ' . $target->getName(); } } /** * 示例用的 A 类 */ class A { public function getName() { return 'Nick'; } } /** * 示例用的 B 类 */ class B { public function getName() { return 'Amy'; } } // 以下代码是主要示例代码 // 创建一个talk类的实例 $talk = new talk; // 将A类绑定至容器,命名为foo Container::bind('foo', function () { return new A; }); // 将B类绑定至容器,命名为bar Container::bind('bar', function () { return new B; }); // 通过容器取出实例 $talk->greet(Container::make('foo')); // hi, Nick $talk->greet(Container::make('bar')); // hi, Amy // 上述例子中,只有在通过make方法获取实例的时候,实例才被创建,这样使得我们可以实现容器,我们依照这一特性,还可以更多的实现高级的特性如事件触发等。利用好匿名函数,可以让应用变得更加丰满。 //彩蛋 匿名函数还可以这样调用:) (function ($name) { echo 'My name is ' . $name; })('jack ma'); // 输出: My name is jack ma ``` 最后修改:2023 年 08 月 11 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏