javascript - Le premier paramètre de setTimeout est d'exécuter la fonction immédiatement, je ne comprends pas
大家讲道理
大家讲道理 2017-07-05 10:56:26
0
9
980

Le premier paramètre de setTimeout est d'exécuter la fonction immédiatement, je n'arrive pas à le comprendre

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    console.log(i);
  })(i), i * 1000);
}

Bien que le résultat soit de sortir 0,1,2,3,4 immédiatement, je ne sais pas pourquoi

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

répondre à tous(9)
给我你的怀抱

De cette façon, tout est imprimé en même temps. . . Ce n'est pas imprimé toutes les secondes. . Il est recommandé d'écrire ainsi. .

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    return function() {
        console.log(i);
    }
  })(i), i * 1000);
}

Laissez-moi vous expliquer pourquoi 0, 1, 2, 3, 4 peuvent être obtenus.
Il existe de nombreux articles sur la pré-interprétation JS sur Internet. La fonction ne sera pas exécutée en entrant dans la phase de contexte d'exécution, quand. vous déclarez cette fonction, elle ne sera pas exécutée tant qu'elle n'est pas appelée. Seule une référence à cette fonction sera enregistrée dans le contexte. On voit que cette fonction est enregistrée en mémoire. La fonction ne sera exécutée que lorsque. ça s'appelle. Laissez-moi parler de ma compréhension, veuillez signaler s'il y a quelque chose qui ne va pas.
Si la fonction n'est pas exécutée immédiatement :
Vous définissez en fait 5 timers dans la boucle for, mais js est monothread, et ces cinq fonctions seront mises dans la file d'attente pour attendre l'exécution. Voici un exemple qui pourrait ne pas être exécuté. être approprié. , vous enregistrez ces cinq fonctions function() {console.log(i);} sous forme de chaînes en mémoire, et il n'y aura aucun mouvement jusqu'à ce que les cinq appels de fonction soient exécutés (qui est le deuxième paramètre de setTimeout lorsque le temps est écoulé). est activé), la fonction commencera à être exécutée, car il y a un i dans la fonction. À ce moment-là, le i sera recherché dans la chaîne de portée, et finalement le i sera trouvé dans la portée extérieure, mais à ce moment-là, le i sera recherché. La boucle for a déjà été exécutée. C'est fini, i est devenu 4, donc cinq 4 seront imprimés
S'il existe une fonction d'exécution immédiate (comme celle que j'ai écrite ci-dessus) :
Vous équivalez en fait à définir 5 timers dans. la boucle for, mais js est monothread, et ces cinq fonctions seront placées dans la file d'attente en attente d'exécution.

(fonction(i) {

return function() {
    console.log(i);
}    

})(i)

Mais parce que la fonction à l'extérieur est exécutée immédiatement, elle sera exécutée immédiatement et i est transmis. Lorsque ces cinq fonctions sont exécutées, i est recherché vers le haut et i se trouve dans la portée de la fonction immédiatement appelée. imprimez 0, 1, 2, 3, 4.

大家讲道理

Vous regardez d'abord les parenthèses qui entourent l'ensemble de la fonction
C'est-à-dire :

(function (i) {
      console.log(i);
})

La compréhension de ce paragraphe est de s'envelopper dans un paquet, un tout, et ce tout est une fonction

Alors, comment appeler la fonction ensuite ? Le nom de la fonction () est-il comme ceci ? Ajoutez des parenthèses après le nom de la fonction et vous pourrez y passer des paramètres

Alors naturellement, voici ce qui s'est passé :

(function (i) {
    console.log(i);
})(i)

Ce type d'appel consiste à écrire une fonction, à l'envelopper avec (), à la suivre avec (), à y écrire les paramètres et à l'exécuter directement

为情所困

Comme mentionné ci-dessus, il s'imprime immédiatement, mais votre setTimeout n'a aucun effet.
La raison est qu'il n'y a pas de valeur de retour après l'exécution de la fonction d'exécution immédiate, elle équivaut donc à setTimeout(undefined, i*1000).

迷茫

setTimeoutNécessite que le premier paramètre soit une fonction, de sorte qu'une fois le temps spécifié par le deuxième paramètre écoulé, la fonction définie par le premier paramètre sera exécutée.

Quand vous écrivez :

for (var i = 0; i < 5; i++) {
  setTimeout(function(i) {
    console.log(i);
  }, i * 1000);
}

Vous remarquerez que la minuterie fonctionne déjà, mais elle n'en imprime qu'une toutes les secondesundefined. Parce que lorsque cette fonction est exécutée, je suis sorti de la boucle et n'a aucune valeur.

Donc vous le changez comme suit :

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    console.log(i);
  })(i), i * 1000);
}

Mais dans ce cas, le premier paramètre n'est pas une fonction, mais une expression, ce qui signifie que la fonction sera exécutée immédiatement. Elle n'attendra pas que le timer prenne effet, mais sera exécutée dès qu'elle sera rencontrée. , donc la forme d'expression consiste à taper directement 0, 1, 2, 3, 4.

Changez-le par ceci selon la déclaration ci-dessus :

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    return function() {
        console.log(i);
    }
  })(i), i * 1000);
}

Bien que le premier paramètre soit une expression, il sera toujours exécuté immédiatement. Cependant, le résultat de l'exécution de cette expression n'est pas de générer une valeur, mais de renvoyer une fonction. Cela satisfait à l'exigence de setTimeout selon laquelle le premier paramètre doit être une fonction. , et donne Les paramètres d'entrée corrects sont définis, donc un résultat correct sera généré toutes les 1 seconde.

Cependant, dans un souci de collaboration en équipe, je ne recommande généralement pas d'écrire comme ceci. Je vous suggère de suivre la méthode d'écriture standard de setTimeout et de l'écrire comme ceci :

.
var j = 0;
for (i = 0; i < 5; i++) {
  setTimeout(function() {
     console.log(j);
     j++;
  }, i * 1000);
}

Cela facilitera au moins la lecture et la compréhension des autres membres du groupe.

我想大声告诉你

Parce qu'il s'agit d'une fonction qui est exécutée immédiatement, bien sûr, elle est affichée immédiatement

淡淡烟草味

Pour les problèmes de portée de fonction, changez simplement le point de ceci.

for (var i = 0; i < 5; i++) {
    setTimeout((function(i) {
        console.log(i);
    }).bind(this,i), i * 1000);
}
習慣沉默

Si la fonction n'est pas exécutée immédiatement, cinq 5 seront imprimés, et ils le seront toutes les secondes, car la fonction dans setTimeout ne sera exécutée que lorsque la boucle sera terminée. À ce moment, la variable globale i est 5. En utilisant la fonction d'exécution immédiate, chaque i dans la boucle sera obtenu. Il y a ici un effet de fermeture. Ce i est maintenant une variable locale et existe dans cette fonction. La valeur de la variable i est différente à chaque exécution.

黄舟
(function(i) {
    console.log(i);
})(i)

Déclaré à exécuter immédiatement. C'est 0 1 2 3 4

Cependant, cela n'a pas de valeur de retour, donc la valeur par défaut est undefined

Votre code peut donc être pensé comme ceci :

for (var i = 0; i < 5; i++) {
  var temp = (function(i) {
    console.log(i);
  })(i); 
  // temp 是 undefined 
  setTimeout(temp, i * 1000);
}

黄舟
  • Comprendre les principes, fermeture, pile, file d'attente d'événements, synchronisation, asynchrone

  • Inversez l'idée : supprimez le paramètre que j'ai transmis et voyez s'il peut s'imprimer normalement. Sinon, analysez pourquoi

  • .
  • Pouvez-vous modifier les méthodes d'écriture pour obtenir le même effet que ci-dessus ? Analysez pourquoi
    Après avoir terminé les points ci-dessus, vous connaîtrez la raison, le processus et le résultat

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal