JS中的闭包和PHP中的闭包有什么区别?它们是否几乎以相同的方式工作?用PHP编写闭包时有什么需要注意的警告吗?
最佳答案
一个区别是两者如何应对存储匿名函数在其中执行的上下文:
// JavaScript:
var a = 1;
var f = function() {
console.log(a);
};
a = 2;
f();
// will echo 2;
// PHP
$a = 1;
$f = function() {
echo $a;
};
$a = 2;
$f();
// will result in a "PHP Notice: Undefined variable: a in Untitled.php on line 5"
要解决此通知,您必须使用use语法:
$a = 1;
$f = function() use ($a) {
echo $a;
};
$a = 2;
$f();
// but this will echo 1 instead of 2 (like JavaScript)
要使匿名函数的行为类似于JavaScript对应的行为,您必须使用引用:
$a = 1;
$f = function() use (&$a) {
echo $a;
};
$a = 2;
$f();
// will echo 2
我认为这是JavaScript和PHP闭包之间最明显的区别。
第二个不同点是,每个JavaScript闭包都有可用的this上下文,这意味着您可以在闭包本身内部使用this(尽管弄清楚this实际指的是通常很复杂)-PHP的当前稳定版本(PHP 5.3)尚不支持闭包内部的$this,但PHP即将发布的版本(PHP 5.4)将支持$this绑定(bind)和使用$closure->bind($this)的重新绑定(bind)(有关更多信息,请参见Object Extension RFC。)
第三个区别是两种语言如何对待分配给对象属性的闭包:
// JavaScript
var a = {
b: function() {}
};
a.b(); // works
// PHP
$a = new stdClass();
$a->b = function() {};
$a->b(); // does not work "PHP Fatal error: Call to undefined method stdClass::b() in Untitled.php on line 4"
$f = $a->b;
$f(); // works though
如果将闭包分配给类定义中的属性,也是如此:
class A {
public $b;
public function __construct() {
$this->b = function() {};
}
public function c() {
$this->b();
}
}
$a = new A();
// neither
$a->b();
// nor
$a->c();
// do work
第四点区别: JavaScript闭包是完全成熟的对象,在PHP中,它们是受限制的对象。例如,PHP闭包不能拥有自己的属性:
$fn = function() {};
$fn->foo = 1;
// -> Catchable fatal error: Closure object cannot have properties
而在JavaScript中,您可以执行以下操作:
var fn = function() {};
fn.foo = 1;
fn.foo; // 1
第五个区别:可以在Javascript中立即调用返回的闭包:
var fn = function() { return function() { alert('Hi');}}
fn()();
不在PHP中:
$fn = function() { return function() { echo('Hi');};};
$fn()(); // syntax error