php 匿名函数主要有两个应用场景:
变量赋值;函数/方法参数;
先看二段匿名函数代码(自己写下这二个闭包分别输出什么值):
$example = function () {
var_dump($message);
};
echo $example();
$message = 'hello';
$example = function () use ($message) {
var_dump($message);
};
echo $example();
上面二个匿名函数被调用时,分别输出 NULL,string(5) "hello"。
下面分析下匿名函数是如何被执行的:
匿名函数在赋值给一个变量时,PHP 会自动进行转化,即把匿名函数转化为闭包的实例,闭包实例内有个方法 __invoke(),__invoke() 的方法体为匿名函数的方法体。所以匿名函数赋值给变量,变量的类型其实是 object,也是闭包类 Closure 的实例。
由原理可知,执行 $example() 时,其实是把 $example 当函数一样调用,会自动触发方法 __invoke()。
__invoke() 说明:
它是 PHP 的一个魔术方法,尝试以调用函数的方式调用一个对象时,__invoke() 会被自动调用。
上面二段代码,第二段为啥会输出 hello 呢?在输出 hello 前,代码到底发生了什么变化?
1,通过匿名函数给变量赋值时,匿名函数自动进行了闭包的实例化。
2,实例化时,use 后面的变量会作为实例的属性,变量值会作为属性值。可以理解为:
$message = 'hello';
$example = function () use ($message) {
var_dump($message);
};
等价于:
$example = new Closure();
$example->message = 'hello';
// 以及下一步讲的 __invoke()
3,匿名函数的函数体会成为 __invoke() 的函数体。匿名函数体用到的变量有二种,一种是匿名函数参数,另一种是 use 后面的变量,参数和平时类的方法参数传递及使用没有区别,但是 use 后面的变量 $message 会在函数体内变为 $this->message。
$example 的打印结果:
附加一段代码,进一步理解一下匿名函数:
function enclosePerson($name)
{
return function ($doCommand) use ($name) {
return sprintf('%s , %s', $name, $doCommand);
};
}
//把字符串“Clay”封装在闭包中
$clay = enclosePerson('Clay');
//传入参数,调用闭包
echo $clay('get me sweat tea!'); // Clay, get me sweat tea!
|