匿名函数
实现一个简单的匿名函数:
$func = function() {
echo "this is a func\n";
};
上面就是一个简单的匿名函数,定义一个函数体,将函数体赋值给一个变量(php5.3之后支持该写法)。
实现闭包
1、当做参数传递:
<?php
// 定义一个匿名函数,赋值给$func
$func = function($param) {
var_dump($param);
};
// 将匿名函数作为参数传入,并调用该参数
function dFunc($func, $param) {
$func($param);
}
dFunc($func, '123'); // 输出:string(3) "123"
2、将匿名函数返回:
<?php
// 定义一个函数,在该函数中将内部的匿名函数返回
function cFunc($param) {
$func = function($param1) use ($param) {
echo "params:".$param1." ".$param;
};
return $func;
}
// 获取并调用匿名函数
$rCFunc = cFunc("123");
$rCFunc("456"); // params:456 123
捕获外界变量
闭包: 闭包是词法作用于的体现,一个持有外部环境自由变量的函数就是闭包。闭包体现的是在程序运行过程中,由 “不确定”变为“ 确定” 的过程。捕获外部变量: 在PHP中对捕获这一动作有了更清晰的表现,使用use关键字。如上面例2。
在上面的例2中,匿名函数$func通过use关键字捕获了外部的自由变量$param,在调用时通过传入cFunc()函数的参数123($param此时会变为“确定”状态),进而调用匿名函数时输出“params:456 123”。
use引入的是自由变量的副本。
例如:
<?php
/*
输出结果:
匿名函数执行前:p1:p1
匿名函数内修改后:p1:p2
匿名函数执行完:p1:p1
*/
function f1() {
$p1 = "p1";
echo "匿名函数执行前:p1:$p1\n";
$func = function() use ($p1) {
$p1 = "p2";
echo "匿名函数内修改后:p1:$p1\n";
};
$func();
echo "匿名函数执行完:p1:$p1\n";
}
f1();
golang闭包: 在golang中同样通过匿名函数实现了闭包,和PHP不同的是,golang中的闭包是默认会引入上下文的自由变量,且引入的地址,即在闭包函数内部修改变量会在函数外部生效。
PHP Closure类
用于代表匿名函数类。在PHP中定义一个闭包函数其实就是一个Closure类的实例。
<?php
/*
输出:
object(Closure)#1 (0) {
}
*/
$func = function() {};
var_dump($func);
类摘要
Closure {
/* 方法 */
__construct ( void )
public static bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] ) : Closure
public bindTo ( object $newthis [, mixed $newscope = 'static' ] ) : Closure
}
- Closure::__construct — 用于禁止实例化的构造函数
- Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
- Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。
Closure::bind
复制一个闭包,绑定指定的$this对象和类作用域,返回一个新的匿名函数
参数说明:
- closure: 需要绑定的匿名函数。
- newthis: 需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。(理解:可以选择是否将匿名函数绑定到一个类对象,若绑定到了一个类对象,则可以在匿名函数内使用
$this
,否则不可使用。)- newscope: 想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性。(理解:如果传入一个类,则可以访问类的static、private、protected属性,否则只能访问public属性。)
简单理解:可以简单理解为将该匿名函数绑定到一个类或实例。根据参数的不同,可以访问不同的类的属性。
<?php
class A{
private static $_cat = 'cat';
private $_dog = 'dog';
public $pig = 'pig';
}
$cat = static function() {
var_dump(A::$_cat);
};
$dog = function() {
var_dump($this->_dog);
};
$pig = function() {
var_dump($this->pig);
};
// 传入null,不可使用$this,但传入A类,则可以访问static等
$bindCat = Closure::bind($cat, null, 'A');
echo "bind cat\n";
$bindCat();
// 传入new A()对象,A类,可以使用$this访问私有属性。
$bindDog = Closure::bind($dog, new A(), 'A');
echo "bind dog\n";
$bindDog();
// 为传入类对象,不可使用$this
$bindDog2 = Closure::bind($dog, null, 'A');
echo "bind dog2\n";
$bindDog2();
输出:
bind cat
string(3) "cat"
bind dog
string(3) "dog"
bind dog2
Fatal error: Using $this when not in object context
Closure::bindTo
Closure::bind()的非静态形式。
小结
- PHP通过匿名函数实现闭包。
- 可以通过将匿名函数作为参数或返回值实现闭包。
- 可以通过use关键字引入外部变量,且引入的变量副本。
- 匿名函数均实现了Closure类,且可以通过Closure::bind()方法将匿名函数绑定到某个类。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。