匿名函数是一类不需要指定标示符,而又可以被调用的函,匿名函数可以方便的作为参数传递给其它函数,最常见应用为回调函数。
闭包(Closure)
说到匿名函数,就不得不提到闭包了,闭包是词法闭包的简称,是引用了自由变量的函数,这个被应用的自由变量将和这个函数一同存在,即使离开了创建它的环境一个一样,所以闭包也可以任务是有函数和其它相关引用组合而成的实体。
使用create_function()创建“匿名”函数
<?php
$array = array(1,2,3,4); array_walk($array,create('$value','echo $value'));
- 1
- 2
- 3
- 1
- 2
- 3
关于另外一个create_function函数的应用
$func = create_function('','echo "Function created dynmic";');
echo $func;// lambda_1 $func();// Function created dynmic $my_func = 'lambda_1 ’ $my_func();// 不存在这个函数 lambda_1();//不存在这个函数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
为什么会出现上面的情况呢?
$func = create_function('', 'echo "Hello";'); $my_func_name = 'lambda_1'; debug_zval_dump($func); // string(9) "lambda_1" refcount(2) debug_zval_dump($my_func_name); // string(8) "lambda_1" refcount(2)
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
显示结果,居然长度都不一样,当然就不一样了。因为系统定义的,函数第一个其实是 \0 也就是空字符。这样因为用户无法定义这样的字符,所以,就不会重名了,聪明吧!!!
这样函数的缺点:
1 函数的定义是通过资产动态eval的,这样就无法进行基本的语法检查
2 这类函数和普通函数没有本质区别,无法实现闭包的效果。
__invoke磨合方法
这个魔术方法被调用的时机是,当一个对象当作函数调用的时候,如果对象定义了__invoke魔术方法则这个函数会被调用.使用方法:
<?php
class Callme{ public function __invoke($phone_num){ echo "Hello $phone_num"; } } $call = new Callme(); $call(13880425377);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
匿名函数的实现
$func = function(){
echo "Hello function"; } echo gettype($func);//object echo get_class($func);//closure
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
原来匿名函数也只是一个普通的类而已。
JS中的匿名函数,可以如下定义:
var a = {};
a.call = function () {alert("called");} a.call();// alert called
- 1
- 2
- 3
- 1
- 2
- 3
闭包的使用
PHP使用闭包(Closure)来实现匿名函数,匿名函数最强大的功能也就在匿名函数所提供的一些动态特征以及闭包效果,匿名函数在定义的时候如果需要使用作用域外的变量,需要如下的语法实现:
<?php
$name = "jingshan";
$func = function()use($name){ echo "hello $name"; } $func();
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
并且匿名函数在每次执行的时候都能访问到上层作用域内的变量,这些变量在匿名函数被销毁之前始终保持这自己的状态,例如如下的例子:
<?php
function getCounter(){ $i = 0; return function() use($i){ echo ++$i; } } $counter = getCounter(); $counter();//1 $counter();//1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
闭包的实现
前面提到匿名函数是通过闭包类实现的,现在我们开始看闭包(类)是怎么实现的。匿名函数和普通函数处理是否有变量名以外并没有区别。
<?php
$i = 100;
$counter = function() use($i){ debug_zval_dump($i); }; $counter();
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
生成的 opcode代码:
然后通过内部函数的调用,实现传参。