Developpez.com - Rubrique JavaScript

Le Club des Développeurs et IT Pro

Testez vos connaissances avec un Quiz sur l'usage avancé des fonctions en JavaScript

Le 2015-01-12 17:49:17, par SylvainPV, Rédacteur/Modérateur


Les fonctions sont un des éléments les plus intéressants du langage JavaScript, mais beaucoup de leurs subtilités restent méconnues. Afin de mesurer vos connaissances et de vous faire découvrir de nouvelles manières d'utiliser les fonctions, un nouveau quiz JavaScript dédié aux fonctions vient d'être publié !

Quiz: Usage avancé des fonctions

Le quiz est de niveau difficile, donc pas de panique si vous n'avez pas la moyenne Et merci de ne pas indiquer des éléments de réponse dans vos commentaires.

Pour les plus chevronnés d'entre vous, je vous propose une onzième question pas piquée des vers. Etant donné son haut niveau d'inintelligibilité, je vous laisse vous échanger des pistes de réflexion publiquement dans les commentaires de ce topic.

QUESTION BONUS
11. A votre avis, à quoi sert la fonction suivante ?
Code :
var f = Function.bind.bind(Function.call);
a) à chaîner des fonctions en gardant toujours le même contexte d'appel
b) à transformer une méthode en fonction classique où l'instance est passée en argument
c) à modifier la fonction bind pour qu'elle exécute les fonctions sur lesquelles on l'appelle
d) à faire s'arracher les cheveux aux collègues

Merci à NoSmoking, SpaceFrog et vermine pour la relecture du quiz.

Participez également à nos autres quizz :
Les quizz JavaScript.
Tous les quizz de Developpez.com dont certains portent sur le CSS, HTML ou PHP.
  Discussion forum
36 commentaires
  • SylvainPV
    Rédacteur/Modérateur
    J'ai justement changé la proposition C de la Q9 avant publication pour lever complètement le doute. Le fait qu'une variable soit dans une portée locale ne permet pas de cacher sa valeur, elles pourront toujours être retrouvées par l'utilisateur final. Ce n'est pas beaucoup plus compliqué de mettre un breakpoint que de fouiller les variables globales. Et ce n'est pas le rôle des closures de toute manière.

    Pour la Q10 la réponse peut être retrouvée dans les spécifications ECMA-262.

    Concernant la question bonus, Kaamo a compris le principe général. Quelqu'un a une idée de à quoi cela pourrait servir ?
  • jhenaff
    Futur Membre du Club
    Ca peut servir a rendre accessibles des fonctions natives plus facilement :
    var f = Function.bind.bind(Function.call);
    var map = f(Array.prototype.map);

    map est directement utilisable sous forme de fonction plutôt que d'appeler a chaque fois Array.prototype.map.call(.....).
    Par contre je pense que c'est moins efficace côté perf (à cause du bind).
  • lysandro
    Membre averti
    Je ne sais pas à quoi servent les clotures au final, je les utilise essentiellement pour émuler le mot-clef 'static' du C, en gros pour avoir des variables rémanentes, ou des fonctions, qui ne polluent pas la portée parente. Bien qu'en C, elles soient définies dans la portée d'utilisation. J'ai souvent été étonné de la confusion entre variables privées et static d'ailleurs.
  • NoSmoking
    Modérateur
    pas en forme ce matin Votre score : 7 / 10 (pas terrible pour un relecteur)

    Envoyé par Kaamo
    Mais à quoi ça peut servir à part donner un contexte d'exécution à maFonction ?
    Je trouve qu'utiliser maFonction.call(context) est plus clair.
    si tu n'as qu'une fois l'écriture à faire oui mais on peut étendre le raccourci à plusieurs fonctions et aller jusqu'à créer des "pseudoMACRO"
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var personne = {
      nom :    'Mac Fly',
      prenom : 'Marty'
    };
    
    var f = Function.bind.bind(Function.call);
    
    function voirNom() {
      console.log(this.prenom +' ' +this.nom);
    }
    function changeNom() {
      this.nom = arguments[0] || 'unknow';
      console.log(this.prenom +' ' +this.nom);
    }
    // pseudo MACRO
    var fct_voir   = f( voirNom);
    var fct_change = f( changeNom);
    on pourra donc écrire
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // version de 'base'
    voirNom.call  (personne);                 // Mac Fly
    changeNom.call( personne, 'En Vacances'); // Marty En Vacances
    
    // version 'bind.bind'
    f( voirNom)( personne);
    f( changeNom)( personne, 'En Vacances');
    
    // version 'macro'
    fct_voir  ( personne);
    fct_change( personne, 'En Vacances');
    bon d'accord il y a d'autres façon de gérer cela.
  • Lcf.vs
    Membre éclairé
    Hum, mea culpa, j'ai dû mal interpréter les chiffres

    Le binding est coûteux, très coûteux mais les appels sont sacrément plus performants avec ton code.

    Pour ce qui est de tester l'usage de la mémoire, j'fais cela sous node

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var i,
        heap,
        cloneArray;
    
    i = 0;
    heap = process.memoryUsage().heapUsed;
    cloneArray = Function.bind.bind(Function.call)(Array.prototype.slice);
    
    for (; i < 99999; i += 1) {
        /*/
        Array.prototype.slice.call([1,2,3]); // 1170304
        /*/
        cloneArray([1,2,3]); // 688264
        //*/
    }
    
    console.log(process.memoryUsage().heapUsed - heap);
  • Kaamo
    Membre émérite
    7/10, c'est mieux que mon score sur le DOM !
    Sympathique ce petit test, j'aurais dû le faire demain matin après le café plutôt qu'en fin de journée, mais ma curiosité a eu le dessus

    Pour la question BONUS, je dirais que c'est une sorte de wrapper qui évite de taper maFonction.call :
    Code javascript :
    1
    2
    3
    4
    5
    function maFonction() { 
      console.log(this.nom); 
    } 
      
    maFonction.call({nom: 'Marty'}); // Marty
    A la place, suffit donc de :
    Code javascript :
    1
    2
    var f = Function.bind.bind(Function.call); 
    f(maFonction)({nom: 'Marty'});
    Mais à quoi ça peut servir à part donner un contexte d'exécution à maFonction ?
    Je trouve qu'utiliser maFonction.call(context) est plus clair.
  • lysandro
    Membre averti
    9/10 mais la réponse à la question 9 est une réponse par défaut
    @Kaamo: sans tester ?

    Ah et merci, ça fait du bien
  • Kaamo
    Membre émérite
    Bien oui sans tester
    J'ai échoué à la 5 et à la 8 & 9 sur les closures. Parce qu'utiliser une closure, c'est cacher la valeur de certaines variables aux utilisateurs selon moi. ça ne peut pas marcher aussi comme réponse ?
  • lysandro
    Membre averti
    Bravo!
    La valeur d'une simple variable locale dans une fonction est aussi cachée pour l'utilisateur, non ?
  • Kaamo
    Membre émérite
    Oui c'est inaccessible via le scope global.
    Je trouve que la réponse 3) de la question 9 pourrait aussi bien être une bonne réponse. En définissant des variables dans une closure, on rend inaccessible leur manipulation des utilisateurs mais pas des développeurs bien sûr