2010-12-04 4 views
2

Si j'ai le code suivant:fermetures et le doute sémantique

function foo() 
{ 
    var a = []; 
    for(var i = 0; i < 3; i++) 
    { 
     a[i] = function(x) 
     { 
      return function() 
      { 
       return x; 
      } 
     }(i); 
    } 
    return a; 
} 

la fermeture est créée quand je l'appelle (i) à chaque itération ou quand je définir les fonctions internes?

puis une expression lambda est une fermeture?

Merci.

Répondre

1

La fermeture est créée en raison du fait que vous renvoyez une fonction qui a accès à la variable locale x, qui a été définie comme le seul membre de la liste des paramètres formels. Donc, les fonctions stockées à a[i] ont fermé autour de leur x unique qui était dans la même portée, et en tant que tel, ont accès à lui. Parce que cette variable est accessible uniquement par cette fonction qui a été transmise de la fonction d'auto-appel, vous avez une fermeture.

Je noterais qu'il serait préférable que vous n'utilisiez pas une fonction anonyme auto-invoquante ici car elle est inutile et ajoute un surcoût. Au lieu de déclarer une fonction nommée, et appelez cela.

function foo() 
{ 
    var a = []; 
    function retain_i(x) 
    { 
     return function() 
     { 
      return x; 
     } 
    } 
    for(var i = 0; i < 3; i++) 
    { 
     a[i] = retain_i(i); 
    } 
    return a; 
} 

EDIT: Pour être plus précis à votre question:

la fermeture est créée quand je l'appelle (i) à chaque itération ...

Non, Cela ne crée pas de fermeture. La fermeture est créée lorsque vous renvoient la fonction qui s'est fermée autour du paramètre x, qui serait autrement inaccessible en dehors de la fonction auto-invoquant.

Si vous n'avez pas retourné cette fonction, vous n'auriez pas de fermeture.

Comme vous pouvez le voir dans l'exemple de code modifié que j'ai donné, la définition/déclaration d'une fonction ne crée pas de fermeture. Plutôt l'exécution d'une fonction qui en sortira une autre fonction qui a accès à des variables autrement inaccessibles crée une fermeture.

+1

Selon le modèle d'environnement, la fermeture est créée * lorsque vous définissez une fonction *. Peu importe si la fermeture survit au contexte survivant ou non. – EFraim

1

La fermeture est créée lorsque vous définissez la fonction, et non lorsque vous l'exécutez, ce que l'on appelle la portée lexicale.

0

Des fermetures sont créées sur les définitions de fonction.

Par conséquent, dans votre exemple, ils sont créés deux fois pour chaque itération - première fois lorsque la function extérieure est déclarée, et une deuxième fois quand il Invoke, la définition d'une fonction interne.

Le résultat affecté à la cellule i du tableau sont des fonctions renvoyant i.

L'autre affiche a raison de l'appeler «portée lexicale» - la plupart des langues modernes semblent l'utiliser.