JS中的闭包和PHP中的闭包有什么不同?它们的工作方式大致相同吗?在用PHP编写闭包时有什么需要注意的地方吗?
发布于 2011-09-14 22:04:08
一个不同之处在于两者如何处理匿名函数在其中执行的上下文的存储:
// 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的当前稳定版本(PHP5.3)还不支持在闭包中使用$this
,但PHP的即将到来的版本(PHP5.4)将支持使用$closure->bind($this)
的$this
绑定和重新绑定(有关更多信息,请参阅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闭包不能有自己的属性:
$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
发布于 2011-09-14 22:04:51
我在PHP中发现的唯一一件事(它非常酷,而且非常方便!)是在类中使用它们作为getters和setters的能力,这在以前一直是一个噩梦,JavaScript可以以相同的方式使用,但它们的行为与我看到的几乎相同。
我不确定两者之间的命名空间约定差异,但正如@Rijk指出的那样,PHP网站上有一个专门介绍它们的部分
<?php
class testing {
private $foo = 'Hello ';
public $bar = 'Bar';
#Act like a getter and setter!
public static $readout = function ($val = null) {
if (!empty($val)) {
testing::$readout = $val;
}
return testing::$readout;
}
}
它们对……来说也很棒。
使用控制器循环访问项,而不是页面上的新for/each循环
非常适合作为参数提供给函数/类
让人讨厌的是……
你不能对它们进行类型转换,因为它们只是函数...
发布于 2011-09-14 21:52:37
它们的工作方式大致相同。下面是关于PHP实现的更多信息:http://php.net/manual/en/functions.anonymous.php
您可以使用闭包(在PHP中称为“匿名函数”)作为回调:
// return array of ids
return array_map( function( $a ) { return $a['item_id']; }, $items_arr );
并将其赋给一个变量:
$greet = function( $string ) { echo 'Hello ' . $string; }; // note the ; !
echo $greet('Rijk'); // "Hello Rijk"
此外,匿名函数“继承”定义它们的作用域-就像JS实现一样,有一个问题:您必须在use()
中列出您想要继承的所有变量
function normalFunction( $parameter ) {
$anonymous = function() use( $parameter ) { /* ... */ };
}
如果您想要修改原始变量,则可以作为参考。
function normalFunction( $parameter ) {
$anonymous = function() use( &$parameter ) { $parameter ++ };
$anonymous();
$parameter; // will be + 1
}
https://stackoverflow.com/questions/7417430
复制相似问题