匿名函数,说白了就是”没有名字的函数”
1 2 3 $foo = function(){ //this is a closure; }
上面声明的就是匿名函数,没有什么特别的,和一般函数结构神似,唯独少了个函数名。并且这个函数可以作为一个值被赋予一个变量或者对象属性 。这种特性是的拥有匿名函数的编程语言在设计一些应用时,更为灵活。
匿名函数和普通函数最大的区别是在于:
匿名函数可以作为一个具体的”值”赋予给变量或者对象属性
匿名函数可以被定义在不同地方,使得它可以有效利用他所在的局域内的变量(或者说上下文环境)
1 2 3 4 5 6 7 8 9 10 11 class foo { public function exec(Closure $callback) { echo $callback();//hi ,nick } } $name = "nick"; (new foo())->exec(function() use ($name){ return "hi ,".$name; });
可以看到,匿名函数使用使用了上下文中的变量$name。而实际上,这个匿名函数实在另一个地方被执行(foo类里面)。这样使得我们不必将变量$name的值通过参数传递到foo类的exec方法中,而且可以减少在exec方法中不必要的处理逻辑,使得类跟家专注于自己的职责;
匿名函数定义时不会被执行,除非被调用,上文中的例子就是这样,利用这种特性,我们可以利用它来实现一个控制反转(IoC)容器 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 /** * 一个简单的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方法获取实例的时候,实例才被创建,使得我们可以实现容器。