Разница в том, как оба справляются с сохранением контекста, в котором выполняется анонимная функция:
// 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
привязку и повторное связывание с использованием $closure->bind($this)
(см. Расширение объекта 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