Закрытие Javascript против закрытия PHP, какая разница?

Каковы различия между закрытием в JS и закрытием в PHP? Они в значительной степени работают одинаково? Есть ли какие-либо оговорки, о которых следует знать при написании закрытий в PHP?

Related of "Закрытие Javascript против закрытия 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 синтаксис 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-расширении Object ).

Третье отличие состоит в том, как оба языка обрабатывают замыкания, назначенные свойствам объекта:

 // 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 Closures не может иметь собственных свойств:

 $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 (это абсолютно здорово и очень удобно!) – это возможность использовать их как геттеры и сеттеры в классах, которые всегда были кошмаром для достижения прежде, 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; } } 

Они также отлично подходят для …

Зацикливание элементов с помощью контроллера, а не нового для каждого цикла на странице

Отлично подходит для предоставления аргументов функциям / классам

Что раздражает их …

Вы не можете их придумать, поскольку они просто функции …

Они работают очень точно так же. Вот еще информация о реализации 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 ) { /* ... */ }; } 

и в качестве ссылки, если вы хотите изменить переменную orignal.

 function normalFunction( $parameter ) { $anonymous = function() use( &$parameter ) { $parameter ++ }; $anonymous(); $parameter; // will be + 1 }