Закрытие Javascript против закрытия PHP, какая разница? - программирование
Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Одно из отличий заключается в том, как справляться с сохранением контекста, в котором выполняется анонимная функция:

// 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 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

Ответ 2

Единственное, что я нашел в 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;
        }
    }

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

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

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

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

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

Ответ 3

Они работают очень точно так же. Здесь дополнительная информация о реализации 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
}