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
我乞求不同。 的确,通常这并不重要。 但有时它很重要。
包含对$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 嗅探来提醒我始终使用静态闭包。
发现了区别:你不能将静态闭包绑定到对象,只能改变对象范围。
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
静态闭包与任何其他静态方法一样,无法访问$this
。
与任何其他方法一样,不访问$this
的非静态闭包通常在静态上下文中工作。
正如你所注意到的,这并不重要。
这就像在类方法上使用 static
关键字一样。如果您不在方法中引用$this
,则不一定需要它(尽管这确实违反了严格的标准)。
我想 PHP 可以解决你的意思是静态访问A
Closure
,因为第二个参数null
bind()