50 votes

Fermetures Javascript vs fermetures PHP, quelle est la différence?

Quelles sont les différences entre les fermetures dans JS et les fermetures en PHP? Travaillent-ils à peu près de la même manière? Y a-t-il des mises en garde à prendre en compte lors de la rédaction de fermetures en PHP?

116voto

Stefan Gehrig Points 47227

Une différence est comment faire face à stocker le contexte dans lequel une fonction anonyme est exécutée:

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

Pour corriger cet avis vous devez utiliser l' use syntaxe:

$a = 1;
$f = function() use ($a) {
    echo $a;
};
$a = 2;
$f();
// but this will echo 1 instead of 2 (like JavaScript)

Pour avoir la fonction anonyme, à se comporter d'une certaine manière comme l'équivalent JavaScript, vous aurez à utiliser des références:

$a = 1;
$f = function() use (&$a) {
    echo $a;
};
$a = 2;
$f();
// will echo 2

Je pense que c'est la différence la plus frappante entre le JavaScript et le PHP fermetures.

Deuxième différence , c'est que chaque JavaScript fermeture a un this contexte de la disposition, ce qui signifie que vous pouvez utiliser this à l'intérieur de la fermeture elle-même (même si c'est souvent assez compliqué de comprendre à quel this , désigne en fait) - PHP de la version stable actuelle (PHP 5.3) ne supporte pas encore $this à l'intérieur d'une clôture, mais PHP prochaine version (PHP 5.4) soutiendra $this de liaison et de travaux de reliure à l'aide de $closure->bind($this) (Voir l' Objet de l'Extension de la RFC pour plus d'info.)

Troisième différence est de savoir comment les deux langues traiter les fermetures attribué aux propriétés de l'objet:

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

Le même est vrai si les fermetures sont affectés à des propriétés dans les définitions de classe:

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

Quatrième différence: JavaScript Fermetures sont à part entière des objets, wheres en PHP, ils sont limités objets. Par exemple, PHP Fermetures ne peut pas avoir de propriétés qui leur sont propres:

$fn = function() {};
$fn->foo = 1;
// -> Catchable fatal error: Closure object cannot have properties

alors qu'en JavaScript que vous pouvez faire:

var fn = function() {};
fn.foo = 1;
fn.foo; // 1

Cinquième différence: Retourné, les fermetures peuvent être immédiatement appelé en Javascript:

var fn = function() { return function() { alert('Hi');}}
fn()();    

Pas en PHP:

$fn = function() { return function() { echo('Hi');};};
$fn()();     // syntax error

4voto

Dave Mackintosh Points 1189

La seule chose que j'ai trouvé en PHP (ce qui est tout à fait cool et vraiment pratique!) c'est la capacité à les utiliser comme des getters et setters dans des classes qui a toujours été un cauchemar pour atteindre avant, JavaScript peut être utilisé de la même manière, mais ils n'agissent presque à l'identique de ce que j'ai vu.

Je ne suis pas sûr au sujet de la namespacing convention de différences entre les deux, mais comme @Rijk a souligné il y a une section sur le site de PHP qui leur est dédié

<?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;
        }
    }

Ils sont également très grand pour...

Boucle sur les éléments avec une manette plutôt qu'un nouveau pour/chaque boucle sur la page

Grande pour fournir d'arguments de fonctions/classes

Ce qui est gênant sur eux...

Vous ne pouvez pas catalogué eux, depuis qu'ils sont juste des fonctions...

2voto

Rijk Points 4855

Ils font à peu près de la même façon. Voici plus d'informations sur l'implémentation PHP: http://php.net/manual/en/functions.anonymous.php

Vous pouvez utiliser un dispositif de fermeture (en PHP appelée "fonction anonyme") comme un rappel:

// return array of ids
return array_map( function( $a ) { return $a['item_id']; }, $items_arr );

et l'assigner à une variable:

$greet = function( $string ) { echo 'Hello ' . $string; }; // note the ; !
echo $greet('Rijk'); // "Hello Rijk"

En outre, la fonction anonyme, 'inherit' le champ dans lequel elles ont été définies comme la JS mise en œuvre, avec un gotcha: vous avez la liste de toutes les variables que vous souhaitez hériter en use():

function normalFunction( $parameter ) {
    $anonymous = function() use( $parameter ) { /* ... */ };
}

et comme une référence, si vous souhaitez modifier l'orignal variable.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X