29

php 文档中的示例Closure::bind包括static匿名函数声明。为什么?如果将其删除,我将找不到区别。

class A {
    private static $sfoo = 1;
}
$cl1 = static function() { // notice the "static"
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1

没有

class A {
    private static $sfoo = 1;
}
$cl1 = function() {
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1
4

4 回答 4

35

发现不同之处:您不能将静态闭包绑定到对象,只能更改对象范围。

class foo { }

$cl = static function() { };

Closure::bind($cl, new foo); // PHP Warning:  Cannot bind an instance to a static closure
Closure::bind($cl, null, 'foo') // you can change the closure scope
于 2013-11-12T03:49:11.097 回答
26

我不敢苟同。的确,很多时候这并不重要。但有时它很重要

持有对 的引用的闭包$this可能会阻止对该对象的垃圾收集,这反过来也可能会显着影响性能。这是一个真正产生巨大差异的示例:

class LargeObject {
    protected $array;

    public function __construct() {
        $this->array = array_fill(0, 2000, 17);
    }

    public function getItemProcessor(): Closure {
        // Try with and without 'static' here
        return static function () {
            // do some processing unrelated to $this
        };
    }
}

$start = microtime(true);

$processors = [];
for ($i = 0; $i < 2000; $i++) {
    $lo = new LargeObject();
    $processors[] = $lo->getItemProcessor();
}

$memory = memory_get_usage() >> 20;
$time = (microtime(true) - $start) * 1000;
printf("This took %dms and %dMB of memory\n", $time, $memory);

这是正常关闭的输出:

This took 55ms and 134MB of memory

这是带有静态闭包的输出:

This took 22ms and 1MB of memory

我在 Debian Buster 上使用 PHP 7.3.19 对此进行了测试,所以是 YMMV。显然,这是一个特殊构造的例子来展示差异。但类似的事情也可能发生在实际应用中。我开始使用 Slevomat 的SlevomatCodingStandard.Functions.StaticClosure嗅探来提醒我始终使用静态闭包。

于 2020-10-22T12:08:12.883 回答
21

与任何其他静态方法一样,静态闭包无法访问$this.

与任何其他方法一样,不访问的非静态闭包$this通常在静态上下文中工作。

于 2019-05-09T14:29:47.533 回答
7

正如您所注意到的,这并不重要。

这就像static在类方法上使用关键字一样。如果您不在方法中引用,则不一定需要$this它(尽管这确实违反了严格的标准)。

我想PHP可以解决你的意思是由于第二个参数而静态Closure访问Anullbind()

于 2013-11-11T05:41:33.583 回答