3071 votes

JavaScript à l'intérieur fermeture à boucle – simple exemple pratique

Les fermetures sont une de ces choses qui ont été beaucoup discuté, mais cette situation apparaît beaucoup pour moi et je suis toujours à la gauche de me gratter la tête.

var funcs = {};
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

Il affiche ceci:

Ma valeur: 3
Ma valeur: 3
Ma valeur: 3

Alors que j'aimerais qu'il sortie:

Ma valeur: 0
Ma valeur: 1
Ma valeur: 2

Quelle est la solution à ce problème de base?

2317voto

harto Points 28479

Eh bien, le problème est que la variable i, dans chacun de vos fonctions anonymes, est lié à la même variable à l'extérieur de la fonction.

Ce que vous voulez faire est de lier la variable à l'intérieur de chaque fonction à un autre, immuable valeur à l'extérieur de la fonction:

var funcs = [];

function createfunc(i) {
    return function() { console.log("My value: " + i); };
}

for (var i = 0; i < 3; i++) {
    funcs[i] = createfunc(i);
}

for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

Depuis il n'y a pas de bloc de portée en JavaScript uniquement fonction de la portée - en enveloppant la fonction de création d'une nouvelle fonction, vous assurer que la valeur de "i" reste comme vous le souhaitez.

404voto

Bjorn Tipling Points 16243

Essayez:

var funcs = [];

for (var i = 0; i < 3; i++) {
    funcs[i] = (function(index) {
        return function() {
            console.log("My value: " + index);
        };
    })(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

374voto

Aust Points 3027

Un autre moyen qui n'a pas encore été mentionnés est l'utilisation de l' Function.prototype.bind

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = function(x) {
        console.log('My value: ' + x);
    }.bind(this, i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

jsFiddle

285voto

neurosnap Points 424

À l'aide d'un Immédiatement appelée à la Fonction de l'Expression, la plus simple et la plus lisible pour délimiter une variable d'index:

for (var i = 0; i < 3; i++) {

    (function(index) {
        console.log('iterator: ' + index);
        //now you can also loop an ajax call here without problems: $.ajax({});
    })(i);

}

Cela envoie l'itérateur i dans la fonction anonyme qui nous définissent en tant que index. Cela crée une fermeture, où la variable i est enregistré pour une utilisation ultérieure dans toute asynchrone des fonctionnalités au sein de la IIFE.

94voto

Darren Clark Points 1489

Une autre façon de le dire est que le je dans votre fonction est liée au moment de l'exécution de la fonction, pas le temps de création de la fonction.

Lorsque vous créez la fermeture, j'ai est une référence à la variable définie à l'extérieur de la portée, non pas une copie de ce qu'il était lorsque vous avez créé la fermeture. Elle sera évaluée au moment de l'exécution.

La plupart des autres réponses fournir des moyens pour contourner par la création d'une autre variable qui ne change pas de valeur sur vous.

Juste pensé que je voudrais ajouter une explication pour plus de clarté. Pour une solution, personnellement, j'irais avec Harto car elle est la plus suffisamment explicites sur la façon de faire de réponses ici. Du code publié au travail, mais je préfère opter pour une fermeture d'usine plutôt que d'avoir à écrire un tas de commentaires pour expliquer pourquoi je suis de déclarer une nouvelle variable(Freddy et 1800) ou ont bizarre intégré de fermeture de la syntaxe(apphacker).

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