PHP匿名函数

2015/05/16

##定义(摘抄自PHP手册) 匿名函数(Anonymous functions),也叫闭包函数(closures),允许创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其他应用的情况。

###匿名函数示例一

<?php echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); }, 'hello-world');

输出

helloWorld

注意:

上面的正则表达式~-([a-z])~中的~表示正则表达式的边界,相当于平常写的正则表达式的//。因此,上面的正则表达式也可以写作/-([a-z])/

闭包函数也可以作为变量来使用。PHP会把此种表达式转换成内置类Closure的对象实例。把一个closure对象赋值给一个变量的方式与普通变量赋值的语法是一样的。最后也要加上分号作为结束。

###匿名函数变量赋值示例

<?php $greet = function($name) { printf("Hello %s\r\n", $name); };

$greet('World'); $greet('PHP');

闭包可以从父作用域中继承变量。任何此类变量都应该使用use语言结构传递进去。

###从父作用域继承变量例子

<?php $message = 'hello';

// 没有使用"use" $example = function () { var_dump($message); }; echo $example();

// 继承 $message $example = function () use ($message) { var_dump($message); }; echo $example();

// 继承变量的值是当函数定义时继承而不是调用时 $message = 'world'; echo $example();

// 重置$message $message = 'hello';

// 通过引用继承 $example = function () use (&$message) { var_dump($message); }; echo $example();

// 值在父作用域的改变影响到了函数调用里面的值 $message = 'world'; echo $example();

// 闭包也接收正常的参数 $example = function ($arg) use ($message) { var_dump($arg . ' ' . $message); }; $example("hello");

上面程序的输出是:

Notice: Undefined variable: message in /example.php on line 6 NULL

string(5) "hello"

string(5) "hello"

string(5) "hello"

string(5) "world"

string(11) "hello world"

这些变量必须在函数或者类的头部声明。从父作用域中继承变量与使用全局变量是不同的。全局变量存在于一个全局的范围,无论当前在执行的是哪个函数。而闭包的父作用域是定义该闭包的函数(不一定是调用它的函数)。

##递归 如果需要递归地调用闭包的话,使用下面的代码:

<?php $recursive = function () use (&$recursive) { //$recursive函数是有效的 };

//这样并不行 $recusive = function() use ($recursive) { //$recursive并不能被识别 };

##注意

1.当'引入'变量到闭包的作用域时,很容易忽略/忘记它们是真的被拷贝到闭包的作用域里而不是仅仅作为可以的值。

因此当你需要在闭包里改变变量的时候,你应该使用引入变量的方式传入。

2.当你调用一个保存在实例化的变量的闭包时是无效的,如下面的代码所示:

<?php $obj = new StdClass();

$obj->func = function() { echo "hello"; }

//$obj->func(); 并不能执行

//应该这样调用: $func = $obj->func(); $func();

//或者 call_user_func($obj->func);

//但是,这样的方式也是可以的: $array['func'] = function() { echo 'hello'; };

$array'func';

##跟Javascript的闭包的几点比较 上面提到,在PHP中通过值传递是这样的

<?php $message = 'hello'; $example = function () use ($message) { var_dump($message); }; $message = 'world'; $example();

上面输出的是hello

在Javascript的闭包可以通过下面的例子实现相同的效果

var message = 'hello';

var func = (function(message) { return function{ alert(message);}})(message); message = 'world'; func();//输出hello

PHP中在使用闭包时的引用传递如下:

<?php $message = 'hello'; $example = function () use (&$message) { var_dump($message); }; $message = 'world'; $example();

上面输出的是world

在Javascript中可以这么实现达到相同的效果:

var message = 'hello'; var func = function() { alert(message); }; message = 'world'; func();//输出world

PHP的闭包与Javascript的闭包有很大的不同。刚开始看到上面的差别时并没有弄懂,后来通过请教同学之后才知道了为什么。上面两端Javascript的不同是因为在Javascript中并没有块作用域以及两个语言之间本身的解析机制的不同。具体的解释日后再写一篇作解释。



通过赞赏码赞助此文