php闭包:为什么在绑定到静态类时,匿名函数声明中的“static”?

2022-08-30 13:50:02

php 文档中的示例 on include on the anonymous function 声明。为什么?如果它被删除,我找不到区别。Closure::bindstatic

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

答案 1

发现区别:你不能将静态闭包绑定到对象,只能更改对象范围。

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

答案 2

我不敢苟同。的确,这通常无关紧要。但有时这很重要。

保存引用的闭包可能会阻止对该对象进行垃圾回收,这反过来又会显著影响性能。这里有一个例子,它确实有很大的不同:$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嗅探来提醒我总是使用静态闭包。


推荐