天天看点

PHP之匿名函数

Closure类,用于代表匿名函数的类。

http://blog.csdn.net/wuxing26jiayou/article/details/51067190

Closure::__construct — 用于禁止实例化的构造函数
Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域
Closure {
/* 方法 */
__construct ( void )
public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
public Closure bindTo ( object $newthis [, mixed $newscope = 'static' ] )
}
           

$closure:表示需要绑定的闭包对象。

$newthis:表示需要绑定到闭包对象的对象,或者null创建未绑定闭包。

$newscope:表示想要给绑定给闭包的类的作用域,可以传入类名或者类的实例,默认值是static,表示不改变,该方法成功时,返回一个新的Closure对象。失败返回false

(不是很理解,后续再看)

在本质上,闭包是将函数内部和函数外部连接起来的桥梁。php匿名函数就是将函数赋值给一个变量中。

匿名函数可用于动态创建函数,并保存到一个变量中

可以看出匿名函数都是Closure的实例。Closure对象。匿名函数可以存储在变量中,打印该变量可以看出是Closure对象。运行该变量就相当于执行了该匿名函数。

<?php
/*
$closure = function ($data) {
   print_r($data);
};

var_dump($closure instanceof Closure);
print_r($closure);
$closure('this is my test');
*/
/**
boolean true
Closure Object ( [parameter] => Array ( [$data] => ) ) this is my test
 */
           

根据传入不同参数返回不同的匿名函数,存储在不同变量中,动态了创建了减法运算和加法运算函数。

function operate($operator) {

    if ($operator == '-') {
        return function ($a, $b) {
            return $a - $b;    
        };
    } else {
        return function ($a, $b) {
            return $a + $b;
        };
    }
}
//返回一个匿名函数
$substraction = operate('-');
//通过该变量可以执行匿名函数
echo $substraction(, );
$add = operate('+');
echo $add(, );
           

Di容器,用来保存对象实例,然后通过set()方法进行注册服务,通过get()方法获取服务。set()方法参数使用了匿名函数。存储在factory变量中,预先注册进来,注册服务都是User的实例。

di−>set实际上并没有实例化,而是等到 di->get()的时候才执行匿名函数new User()并将对象返回,然后通过该对象我们可以调用相关的方法。

按需实例化,不用则不实例化,提高效率,懒加载方式。

class Di {

    private $_factory;

    public function set($id, $value) {
        $this->_factory[$id] = $value;
    }

    public function get($id) {
        $value = $this->_factory[$id];
        return $value();
    }
}

class User{

    private $_username;

    public function __construct($username)
    {
        $this->_username = $username;
    }

    public function getUserName() {
        return $this->_username;
    }
}

$di = new Di();
$di->set('zhangsan', function () {
    return new User('张三');
});

/*
print_r($di);
 * Di Object ( [_factory:Di:private] => Array ( [zhangsan] => Closure Object ( ) ) )
 */
/**
print_r($di->get('zhangsan'));
 * User Object ( [_username:User:private] => 张三 )
 */
print_r($di->get('zhangsan')->getUserName());//张三
           

父函数里面可以定义子函数,父函数变量在子函数中可以通过use来进行传递使用。

注意:use()里面的变量只能算是外部变量的一个副本,如果要改变外部变量的值,需要改为引用,加上&变量名

function cloDemo($data = '') {
    return function ($a, $b) use($data) {
        print_r("now sub var is a=".$a." and var b =".$b." and parent data is =".$data);
    };
}

$demo = cloDemo('我是张三');
$demo('匿名函数参数a', '匿名函数参数b');
           

总结

匿名函数可以赋值给一个变量;也可以当做参数进行传递;也可以在普通函数里面使用它(传给一个变量、作为函数返回等)

闭包的代码相对优雅,但是逻辑比较容易混淆,相比其他方式执行效率相对较低,要慎用。建议在代码结构比较乱,需要封装的时候使用。