匿名函数
在谈闭包之前,先说一下匿名函数,匿名函数实际上相当于把函数当做变量,不需要专门去定义一个函数。
在匿名函数出现之前,如果想把函数当做变量传递,得用字符串的形式,如下:
$anonymous = function (){ echo "hello ";};
function normal(){
echo "world";
}
function testAnonymous($func){
$func();
}
testAnonymous($anonymous);
testAnonymous('normal');
ps:另外php还提供了一个在运行时动态创建函数的方法,create_function
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc
";
echo $newfunc(2, M_E) . "
";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
奇特的是这个create_function生成的函数居然是lambda_1类型,而不是Closure。
闭包
然而匿名函数中不能使用外部变量,为了解决这个问题,出现了闭包。
闭包可以捕获外部环境中的变量,由于在php中是早绑定,在闭包定义时,传入闭包的值就确定了。
如果外部变量发生了改变,那么闭包中的变量是不会变的,而且我们在闭包中也不能修改外部值。
解决办法是使用引用传值,在捕获的变量前添加&。
function test(){
$v = "hello";
$closure1 = function () use ($v){
return $v;
};
$closure2 = function () use (&$v){
return $v;
};
$v = "world";
echo "closure1:".$closure1();
echo "
";
echo "closure2:".$closure2();
}
test();
另外如果在类中使用闭包,如过php版本低于5.3,是不能使用$this的。
闭包会编译成opcode并缓存起来,而create_function是在运行时动态创建,效率要比闭包低,建议使用闭包。