Pages

Affichage des articles dont le libellé est closure. Afficher tous les articles
Affichage des articles dont le libellé est closure. Afficher tous les articles

Evaluez les expressions

déterminer l'affichage dans les deux cas !

function f1(){
    var a=1; 
    return f2();
}
function f2(){
    return a;
}

console.log(f1());

function g1(){               
   var a=1;               
   
   function f2(){
       return a;
   }
   return f2();
}
console.log(g1());

Nous devrons apprendre la notion de 

  1. portée lexical et 
  2. closure

perte du this : objet

Voici un exemple montrant la perte de la référence du this dans les objets.

function P() {

  this.age = 0;

  setInterval(function () {
    this.age++; // this ref sur global et non l'objet
  }, 1000);
}
var pPerte = new P();


En voici une version corrigée ! Les fonctions fléchées capturent la valeur this de leur contexte.

function Personne() {
  this.age = 0;

  setInterval(() => this.age++, 1000);
}

var p = new Personne();

setInterval(() => console.log(p.age), 3000);



Une autre solution fût l'utilisation de bind

Closure : one more


me = {
   name : "denis",
   age : 50
}

you = {
   name : "anonymous",
   age : 45
}


function greaterThan(n) {
  return function(m) { return m > n; };
}
var greaterThanMe = greaterThan(me.age);
console.log(greaterThanMe(you.age));



Closure

Une des caractéristiques de la  "closure" est que le context n'est jamais inclue dans la closure !

 id = "val";

$( '*' ).each( function () {
     console.log( id );
}

 this .id = "val";
$( '*' ).each( function () {
     console.log(  this .id );
}

 this  est en réalité lié à chaque élément de la boucle. LA correction sera de créer une copie qui est inclue dans la closure.

this.id = "val";
var outer = this;
$( '*' ).each( function () {
     console.log( outer.id );

Portées des variables

Nous allons étudier la portée des variables à travers l'exemple suivant.
 
(function(){
  
  function A() {
    var aFixe= 2;
    var aVar = new Date().getMilliseconds();
    
    function modAVar(){
        var aFixe= 10000;
        aVar = new Date().getMilliseconds();
    }
    
    function B() {
        console.log('aFixe = ' + aFixe + "\n" + "  aVar = " + aVar);
     }

// affichage initial
     B();

// modification de aVar dans 2 second
     setTimeout(modAVar,2000); 
    
// affichage dans 3 seconde pour attendre l'effet de la modification
     setTimeout(B,3000);
  } 

// lancement du test
  A();
  
  
})();

Portée des variables on jsbin.com

Pour aller plus loin et comprendre un problème classique



Une closure permet de référencer une variable qui existe dans la fonction parent. 
Cependant, elle ne fournit pas la valeur de la variable au moment de sa création, mais fournit la dernière des valeurs dans la fonction parent. La variable de boucle utilisée comme itérateur pose donc le problème lors de l'appel de la deuxième fonction.

JS Bin on jsbin.com

 Cours

 

Passage de paramêtres Event

Prenons l'exemple de mozilla pour illustrer le passage de paramètre à un événement
JS Bin on jsbin.com

JS Bin on jsbin.com
JS Bin on jsbin.com
Cette solution n'est pas applicables dans le cas de boucles !
 Les closures sont très utiles pour le passages de paramètre lors d'un événement
JS Bin on jsbin.com

Closure encore et encore

JS Bin

JS Bin
Vous pouvez écrire vous même du code pour animer vos pages (exemple). Mais aujourd'hui, de nombreuses bibliothèques proposent des effets d'animation (exemple).



Introduction

Etudier le code permettant de rendre un effet sur un élément.

function effet( elem ) {

    // init : Start for example the slide down or the opacity at 0
    fx(0);

    // Show the element (but you can't see it, since the height or opacity is 0
    show( elem );


    // We are going to do a 20 frame animation that takes
    // place over one second
    for ( var i = 0; i <= 100; i += 5 ) {
        // A closure to make sure that we have the right i
        (function(){
            var pos = i;

            // Set the timeout to occur at the specified time in the future
            setTimeout(function(){

                // Set the new height  or opacity of the element
                fx(pos);

            }, ( pos + 1 ) * 10 );
        })();
    }
}

Exemple

Dans le code précédant remplaçons fx() par  elem.style.height.

function slideDown( elem ) {
    // Start the slide down at  0
    elem.style.height = '0px';

    // Show the element (but you can't see it, since the height is 0)
    show( elem );

    // Find the full, potential, height of the element
    var h = fullHeight( elem );

    // We are going to do a 20 frame animation that takes
    // place over one second
    for ( var i = 0; i <= 100; i += 5 ) {
        // A closure to make sure that we have the right i
        (function(){
            var pos = i;

            // Set the timeout to occur at the specified time in the future
            setTimeout(function(){

                // Set the new height of the element
                elem.style.height = (( pos / 100 ) * h ) + "px";

            }, ( pos + 1 ) * 10 );
        })();
    }
}

Fade-in

On cherchera à remplacer  fx par une fonction permettant de créer un effet d'apparition.


        (function(pos){
            setTimeout(function(){
                elem.style.height = (( pos / 100 ) * h ) + "px";
                elem.style.width = (( pos / 100 ) * h ) + "px";
                elem.style.opacity=  pos / 100 ;
            }, ( pos + 1 ) * 10 );
        })(i);


Vous pouvez voir ce code en action (ici).

3 closures

setTimeout :


Array


return function


Closure

Comprendre la chaîne de scoop : partie 2


L'objectif de cette partie est de comprendre le comportement de ce code :

function parent() {

 var x = 10;  return function() {console.log(x)}
} 
var closure = parent();
var x = 20;
closure(); // console.log(x) ?



Vous devez avoir lu l'article sur la portée des variables.

L'idée est simple : Permettre à une fonction d'utiliser une variable en dehors de son environnement local.






Closure en action : Protection de l'environnement

Scope : portée des variables !

Objectif

L'objectif de cette partie est de comprendre la chaîne de Scoop.


La compréhension de la portée (scope) des variables en Javascipt est fondamentale ! Cette notion ouvre la porte à la notion de closure : un des fondement de Javascript.

Dans un langage nous manipulons des variables, des fonctions des objets. Il doit donc y avoir des règles pour connaitre l'existence de ces différents éléments pour pouvoir les manipuler.

Nous allons définir deux termes : lexical scope et execution context !

Nous allons commencer par imaginer un modèle simple de boites dans des boites


Lexical context

Il est difficile de comprendre cette notion. Le contexte lexical se définit lors de la définition pour rechercher les portée des variables. Il faudra attendre l'exécution pour avoir la valeur de ces variables.

Pour nous faciliter et nous convaincre de son existence, nous allons nous aider du débogueur.



Exécution : 

Nous allons suivre l'exécution de la fonction à l'aide du débogeur.




Exerçons nous sur un exemple de passage de paramètres.

<script>

var x = 1 ;

function add(x){
    x++;
    console.log(x);
    return true;
}

add(x);
console.log(x);

</script>

Voici des copies d'écran qui permettent de suivre la valeur de x, à la fois comme "formal et actual" parameters) ! 

Nous observons que la valeur de x (la valeur du "actual parameter") est égale à 2 dans la fonction.


Cette variable n'est qu'une copie de x.
Vérifions la valeur de x dans l'espace global. Elle est toujours à 2.



Nous pourrions comparer cet exemple avec le passage par adresse.

<script>

var x = 1 ;

function add(){
    x++;
    console.log(x);
    return true;
}

add();
console.log(x);

</script>

Dans ce cas la valeur est modifiée.


Summary

  1. Definition of lexical : 'The region in your source code where you can refer to variables by name without getting access errors.'
  2. New lexical scopes are created every time you make a new function definition. (En C les blocks définissent des portées)
  3. Variables defined within a lexical scope cannot be accessed outside that scope.
  4. Remember to use the var keyword when you make a new variable in a scope (it is not required by the language, but you should always do it! If you do not use var, the variable will be placed in the global namespace - don’t use this 'feature' to accomplish that, it’s bad).
  5. The global scope is shared between (.js) files. 


Execution Contexts ('in-memory scopes') in JavaScript:

  • A new execution context is created each time you run a function.

(source udacity).