本文依旧以php为主。
匿名函数,说白了就是“没有名字的函数”,恩废话。给一段代码可能更为直白:
- $foo = function() {
- // this is a closure
- }
对,这就是匿名函数,没什么特别的,和一般函数结构神似,唯独少了个函数名。而且这个函数可以作为一个值被赋予一个变量或者对象属性。这种特性使得拥有匿名函数的编程语言再设计一些应用时,更为灵活。
匿名函数和普通函数最大的区别是在于,匿名函数可以作为一个具体的“值”赋予给变量或者对象属性,其次,由于匿名函数可以被定义在不同地方,使得他可以有效利用他所在的局域内的变量(或者说上下文中的变量)。下面例子中就是这样一种情况。
- 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方法获取实例的时候,实例才被创建,这样使得我们可以实现容器,我们依照这一特性,还可以更多的实现高级的特性如事件触发等。利用好匿名函数,可以让应用变得更加丰满。
https://www.insp.top/article/we-need-to-know-something-about-closure
相关博文
匿名函数的那些事儿