Javascriptclosuresvs PHPclosures,有什么区别?
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和PHPclosures之间最显着的区别。
第二个区别在于,每个JavaScript闭包都有一个可用的上下文,这意味着您可以在闭包本身内部使用它(尽pipe弄清楚this
实际上指的是什么)通常很复杂 – PHP当前的稳定版本(PHP 5.3)没有但是在一个闭包中支持$this
,但是即将到来的PHP版本(PHP 5.4)将支持$this
绑定,并使用$closure->bind($this)
重新$closure->bind($this)
(请参阅Object Extension RFC获取更多信息。
第三个区别是两种语言如何处理分配给对象属性的闭包:
// JavaScript var a = { b: function() {} }; ab(); // 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
我在PHP中发现的唯一的东西就是能够将它们作为getter和setter来使用,而这些是前所未有的噩梦,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; } }
他们也非常适合…
使用控制器循环播放项目,而不是在页面上使用新的/每个循环
非常适合作为参数提供给函数/类
有什么恼人的是…
你不能形容他们,因为他们只是function…
他们的工作方式也差不多。 下面是关于PHP实现的更多信息: http : //php.net/manual/en/functions.anonymous.php
您可以使用闭包(在PHP中称为“匿名函数”)作为callback:
// return array of ids return array_map( function( $a ) { return $a['item_id']; }, $items_arr );
并将其分配给一个variables:
$greet = function( $string ) { echo 'Hello ' . $string; }; // note the ; ! echo $greet('Rijk'); // "Hello Rijk"
而且,匿名函数“inheritance”了它们被定义的范围 – 就像JS实现一样, 有一个问题 :你必须在use()
列出你想要inheritance的所有variables:
function normalFunction( $parameter ) { $anonymous = function() use( $parameter ) { /* ... */ }; }
并作为参考,如果你想修改orignalvariables。
function normalFunction( $parameter ) { $anonymous = function() use( &$parameter ) { $parameter ++ }; $anonymous(); $parameter; // will be + 1 }