Les fermetures de Javascript et les effets secondaires en anglais simple? (séparément)

J'ai lu des livres de JavaScript et j'ai toujours entendu parler de fermetures et d'effets secondaires. Pour une raison quelconque, je ne comprends pas ce qu'ils sont réellement. Est-ce que quelqu'un peut m'expliquer ce qu'ils sont en anglais plus simple? (Comme vous l'expliquiez à quelqu'un avec le niveau de programmation d'un graphiste).

Les effets secondaires sont le concept plus facile. Une "fonction pure" est une fonction qui mappe sa (s) valeur (s) d'entrée dans une valeur de sortie def plus(x, y){ return x + y; } def plus(x, y){ return x + y; } . Un «effet secondaire» est un effet autre que cette valeur de retour. Ainsi, par exemple:

 def plusWithSideEffects(x, y) { alert("This is a side effect"); return x + y; } 

A l'effet secondaire d'élever un dialogue d'alerte (et nécessitant une interaction de l'utilisateur). Chaque fonction de code a des effets secondaires (ils consomment tous de la mémoire et prennent du temps, sinon rien d'autre), mais lorsque les gens parlent d'effets secondaires, ils sont souvent plus concernés par l'IO (comme la boîte de dialogue d'alerte ci-dessus) ou l'écriture d'état Vit au-delà de la période d'exécution de la fonction.

Le défi avec les effets secondaires est qu'ils rendent les fonctions plus difficiles à raisonner et à réutiliser. (Il est beaucoup plus facile de raisonner et de réutiliser des fonctions aussi proches que possible des «fonctions pures», car elles ont tendance à «faire une bonne chose».)

Les fonctions avec effets secondaires font autre chose que le renvoi d'une valeur (bien qu'elles puissent également le faire). Si vous pouvez remplacer tous les appels de fonction pour des arguments donnés avec la valeur de ces arguments et que le programme a le même comportement, il n'y a pas d'effets secondaires. Cela nécessite que la fonction renvoie toujours la même valeur pour les arguments donnés.

C'est-à-dire supposons f(1,2) == 12 . Si vous pouvez toujours remplacer f(1,2) avec 12 et que le programme se comporte de la même manière, alors f n'a pas d'effets secondaires pour ces arguments. D'autre part, si dans un endroit f(1,2) == 12 et un autre f(1,2) == 13 , alors f a des effets secondaires. De même, si le programme a cessé d'envoyer un courrier électronique après avoir remplacé f(1,2) par 12, alors f a des effets secondaires. Généralement, si f(x,y) == z (où z dépend de x et y) et vous pouvez toujours remplacer chaque appel f(x,y) par z , alors f n'a pas d'effets secondaires.

Quelques fonctions simples avec effets secondaires:

 // doesn't always return the same value function counter() { // globals are bad return ++x; } // omitting calls to `say` change logging behavior function say(x) { console.log(x); return x; } 

Effet secondaire:

Pensez à un effet secondaire comme quelque chose qui fait deux choses à la fois. Par exemple:

Exemple classique d'un effet secondaire:

 var i = 1; var j = i++; 

L'effet secondaire se produit à i++ . Ce qui se passe ici est j devient 1 et puis i incrémenté et devient 2. En d'autres termes, deux choses sont arrivées et l'effet secondaire est que i devenu 2.

Fermeture:

Visualisez une chaîne de liens comme ceci: <> <> <> <> <> <> <>. Imaginez que le nom de cette chaîne de liens s'appelle la chaîne de portée . Ensuite, imaginez que tous ces liens relient les objets comme ceci: objet <> objet <> objet <> objet <>. Maintenant, gardez à l'esprit ce qui suit:

(1) Toutes les chaînes de portée commencent par l'objet global .

(2) Lorsqu'une fonction est définie, une chaîne de portée pour cette fonction est stockée .

(3) Lorsqu'une fonction est invoquée, elle crée un nouvel objet et l'ajoute à la chaîne de portée.

Maintenant, regardez l'exemple suivant:

 function counter () { // define counter var count = 0; return function () { return count + 1;}; // define anonymous function }; var count = counter(); // invoke counter 

Dans cet exemple, lorsque counter() est défini, la chaîne de portée pour le compteur ressemble à ceci: <> objet global <>. Ensuite, lorsque le counter() est invoqué, la chaîne de la portée se présente comme suit: <> objet global <> objet de compteur <>. Après cela, la fonction sans nom (appelé une fonction anonyme) dans le compteur interne est définie et invoquée. La chaîne de portée pour la fonction anonyme une fois invoquée ressemble à ceci: <> objet global <> objet de compteur <> objet de fonction anonyme <>

Dans ce cas, la partie de fermeture est disponible. Si vous remarquez, la fonction anonyme utilise le count variable qui a été défini en dehors de celui-ci. La raison en est parce que la fonction anonyme peut accéder à toutes les variables définies dans sa chaîne de portée . C'est ce qu'est une fermeture, une fonction avec des références à toutes les variables dans sa chaîne de portée stockée.

Cependant, dans l'exemple ci-dessus, une fois que les fonctions sont retournées, les objets créés à l'invocation sont éliminés, donc il n'y a vraiment aucun but. Regardez maintenant ce qui suit:

 function counter () { // define counter var count = 0; function f() { return count + 1;}; // define f return f; // return f }; var count = counter(); // invoke counter 

Dans cet exemple, je renvoie une fonction appelée f et attribue celle au count variables. Maintenant, le count variables contient une référence à l'ensemble de la chaîne de périmètre et il n'est pas éliminé. En d'autres termes, le nombre de variables stocke la chaîne de portée comme ceci: <> objet global <> objet de compteur <> objet de fonction anonyme <>. C'est le pouvoir des fermetures, vous pouvez tenir une référence à une chaîne de portée et l'appeler comme ceci: count() .

Exemple

 function outer() { var outerVar; var func = function() { var innerVar ... x = innerVar + outerVar } return func } 

Lorsque external () meurt, function func () continue à vivre et cette utilisation est pratique

Je suis nouveau sur JavaScript, et je n'essaierai pas de parler de fermetures. Cependant, ma nouveauté pour JavaScript me rend très conscient de l'utilisation d'effets secondaires impossibles dans mon langage de programmation habituel (Erlang).

Les effets secondaires semblent être un moyen habituel de changer d'état en JavaScript. Prenez par exemple cet exemple du site Web w3cschools.com:

 <script> function myFunction() { document.getElementById("demo").innerHTML = "Paragraph changed."; } </script> 

Ici, il n'y a pas de paramètres d'entrée ou de valeur de retour, mais le contenu du document est modifié, car ils sont globalement accessibles à la fonction. Si vous étiez en train d'écrire ceci dans Erlang par exemple, le document serait transmis en tant que paramètre et le nouvel état du document serait retourné. Une personne lisant le programme d'appel verrait un document passé et un document modifié en cours de retour.

Voir les fonctions appelées à ne pas renvoyer un nouvel état explicite devrait alerter le programmeur sur l'utilisation probable d'effets secondaires.