La compréhension de la variable de capture par les closures en Javascript/Nœud
Est-il une source précise sur la variable de capture en Javascript en dehors de la norme (c'est chiant à lire)?
Dans le code suivant i
est copié par valeur:
for (var i = 0; i < 10; i++)
{
(function (i)
{
process.nextTick(function ()
{
console.log(i)
})
}) (i)
}
De sorte qu'il imprime 1..10. process.nextTick
est un analogue de setTimeout(f,0)
dans le nœud.
Mais dans le prochain code que j'ai ne semble pas être copié:
for (var i = 0; i < 10; i++)
{
var j = i
process.nextTick(function ()
{
console.log(j)
})
}
Il imprime 9 10 fois. Pourquoi? Je suis plus intéressé par une référence générale à l'article que dans l'explication de ce cas concret de capture.
Vous devez vous connecter pour publier un commentaire.
Je n'ai pas de référence pratique. Mais la ligne de fond est la suivante: Dans la première, vous êtes explicitement en passant
i
à une fonction anonyme, ce qui crée un nouveau champ d'application. Vous n'êtes pas de la création d'un nouveau champ d'application, soiti
ouj
dans le second. Aussi, JavaScript toujours capture des variables, et non des valeurs. Donc vous seriez en mesure de modifier moi aussi, j'.Le JavaScript
var
mot a portée de la fonction, pas le bloc de portée. Donc une boucle for ne crée pas de champ d'application.Comme une note, le non-standard
let
mot a une portée locale.let
avec--harmony_block_scoping
ligne de commande argIl est copié (ou affecté) dans votre deuxième exemple, c'est juste qu'il n'y a qu'une seule copie de la variable
j
et il aura la valeur que ce dernier avait dans laquelle sera 9 (la dernière rev de votre pour la boucle). Vous avez besoin d'une nouvelle fonction de fermeture pour créer une nouvelle copie d'une variable pour chaque rev de lafor
boucle. Votre deuxième exemple a juste une variable qui est commun à tous les tours de votrefor
boucle, donc il ne peut avoir qu'une seule valeur.Je ne sais pas du tout définitif writeup sur ce sujet.
Variables en javascript sont limités au niveau de la fonction. Il n'y a pas de bloc de portée en javascript. En tant que tel, si vous voulez une nouvelle version d'une variable pour chaque rev de la boucle for, vous devez utiliser une nouvelle fonction (création d'une fonction de fermeture) pour capturer cette nouvelle valeur à chaque fois grâce à la
for
boucle. Sans la fonction de fermeture, la seule variable va juste avoir une valeur qui sera commun à tous les utilisateurs de cette variable.Lorsque vous déclarez une variable comme votre
var j = i;
à un emplacement autre que le début de la fonction, javascript palans à la définition du haut de la fonction et de votre code devient équivalent à ceci:Ce qui est appelé
variable hoisting
et est un terme que vous pourriez Google si vous voulez en savoir plus sur elle. Mais, le point est qu'il est uniquement fonction de la portée, de sorte qu'une variable déclarée dans une fonction est en fait déclaré une fois au sommet de la fonction, puis assigné à n'importe où dans la fonction.Le Mozilla Developer Network a une très belle écriture-up:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
En JavaScript, les fonctions joindre variables qui ont été définis dans un champ à l'extérieur de leur propre dans une telle manière qu'ils ont une "vie" de référence à la variable, pas un instantané de sa valeur à un moment donné.
Donc, dans votre deuxième exemple, la création de dix fonctions anonymes (dans
process.nextTick(function(){...})
) qui joindre la variablej
(eti
, qui ont toujours la même valeur lorsque la fonction anonyme est créé). Chacune de ces fonctions, utilisez la valeur dej
à un moment après l'extérieur de la boucle est exécuté entièrement, de sortej=i=10
au moment de chacune de ces fonctions est appelée. C'est, d'abord votre boucle for s'exécute entièrement, puis votre anonyme fonctions de s'exécuter et d'utiliser la valeur dej
, qui est d'ores et déjà 10!Dans votre premier exemple, la situation est un peu différente. En enveloppant l'appel à
process.nextTick(...)
dans son propre fonction anonyme et par la liaison de la valeur dei
dans une fonction locale par l'appel de la fonction wrapper (et, accessoirement, ombrage l'ancienne variablei
dans le paramètre de la fonctioni
), de l'acquisition de la valeur de la variablei
à moment, au lieu de conserver le clos de référence ài
dont la valeur change dans l'enceinte de l'intérieur d'une fonction anonyme.À clarifier votre premier exemple un peu, essayez de modifier les anonymes fonction wrapper pour utiliser un argument nommé
x
((function (x) { process.nextTick(...); })(i)
). Ici, nous voyons clairement quex
prend la valeuri
pour le moment, la fonction anonyme est appelé ainsi, elle permettra d'obtenir chacune des valeurs dans la boucle for (1..10).