[ Web Proxy ]
URL:
Viewing: https://fr.javascript.info/iterable [Back]  [Original]

Iterables
FR

Nous souhaitons rendre ce projet open source disponible pour les gens du monde entier.

Aidez-nous traduire le contenu de ce tutoriel dans votre langue!

    Rechercher sur Javascript.info:
    Rechercher dans le tutoriel:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Les objets Iterable sont une gnralisation des tableaux. Cest un concept qui permet de rendre nimporte quel objet utilisable dans une boucle for..of.

    Bien sr, les tableaux sont itrables. Mais il existe de nombreux autres objets intgrs, qui sont galement itrables. Par exemple, les chanes de caractres sont galement itrables.

    Si un objet nest pas techniquement un tableau, mais reprsente une collection (liste, set) de quelque chose, alors for..of est une excellente syntaxe pour boucler dessus, voyons comment le faire fonctionner.

    Symbol.iterator

    Nous pouvons facilement saisir le concept des itrables en faisant le ntre.

    Par exemple, nous avons un objet qui nest pas un tableau, mais qui semble convenir pour une boucle for..of.

    Comme un objet range qui reprsente un intervalle de nombres :

    let range = {
      from: 1,
      to: 5
    };
    
    // Nous voulons que le for..of fonctionne :
    // for (let num of range) ... num=1,2,3,4,5

    Pour rendre la range itrable (et donc laisser for..of faire son travail), nous devons ajouter une mthode lobjet nomm Symbol.iterator (un symbole intgr spcial que pour cela).

    1. Lorsque for..of dmarre, il appelle cette mthode une fois (ou des erreurs si il nest pas trouv). La mthode doit retourner un iterator un objet avec la mthode next.
    2. partir de l, for..of ne fonctionne quavec cet objet retourn.
    3. Quand for..of veut la valeur suivante, il appelle next() sur cet objet.
    4. Le rsultat de next() doit avoir la forme {done: Boolean, value: any}, o done = true signifie que litration est termine, sinon value doit tre la nouvelle valeur.

    Voici limplmentation complte de range avec les remarques :

    let range = {
      from: 1,
      to: 5
    };
    
    // 1. l'appel d'un for..of appelle initialement ceci
    range[Symbol.iterator] = function() {
    
      // ...il retourne l'objet itrateur :
      // 2.  partir de l, for..of fonctionne uniquement avec cet itrateur, lui demandant les valeurs suivantes
      return {
        current: this.from,
        last: this.to,
    
        // 3. next() est appele  chaque itration par la boucle for..of
        next() {
          // 4. il devrait renvoyer la valeur sous forme d'objet {done: .., valeur: ...}
          if (this.current <= this.last) {
            return { done: false, value: this.current++ };
          } else {
            return { done: true };
          }
        }
      };
    };
    
    // maintenant a marche !
    for (let num of range) {
      alert(num); // 1, ensuite 2, 3, 4, 5
    }

    Veuillez noter la fonctionnalit principale des iterables : separation of concerns (sparation des proccupations).

    • Le range lui-mme na pas la mthode next().
    • Au lieu de cela, un autre objet, appel iterator, est cr par lappel range[Symbol.iterator](), et sa mthode next() gnre des valeurs pour litration.

    Ainsi, lobjet itrateur est spar de lobjet sur lequel il est itr.

    Techniquement, nous pouvons les fusionner et utiliser range lui-mme comme itrateur pour simplifier le code.

    Comme a :

    let range = {
      from: 1,
      to: 5,
    
      [Symbol.iterator]() {
        this.current = this.from;
        return this;
      },
    
      next() {
        if (this.current <= this.to) {
          return { done: false, value: this.current++ };
        } else {
          return { done: true };
        }
      }
    };
    
    for (let num of range) {
      alert(num); // 1, ensuite 2, 3, 4, 5
    }

    Maintenant, range[Symbol.iterator]() renvoie lobjet range lui-mme : il dispose de la mthode next() et se souvient de la progression de litration en cours dans this.current. Cest plus court? Oui. Et parfois cest aussi bien.

    Linconvnient est quil est maintenant impossible davoir deux boucles for..of sexcutant simultanment sur lobjet: elles partageront ltat ditration, car il ny a quun seul itrateur lobjet lui-mme. Cependant, il est rare de disposer de deux for-of parallles, faisables avec certains scnarios asynchrones.

    Itrateurs infinis

    Des itrateurs infinis sont galement possibles. Par exemple, range devient infini pour range.to = Infinity. Ou nous pouvons crer un objet itrable qui gnre une suite infinie de nombres pseudo-alatoires. Il peut tre aussi utile.

    Il ny a pas de limitation sur next, il peut renvoyer de plus en plus de valeurs, cest normal.

    Bien sr, la boucle for..of sur une telle itration serait sans fin. Mais on peut toujours larrter en utilisant break.

    String est iterable

    Les tableaux et les chanes de caractres sont les iterables intgrs les plus largement utiliss.

    Pour une chane de caractres, for..of boucle sur ses caractres :

    for (let char of "test") {
      // se dclenche 4 fois: une fois pour chaque caractre
      alert( char ); // t, ensuite e, ensuite s, ensuite t
    }

    Et cela fonctionne correctement avec les paires de substitution !

    let str = '';
    for (let char of str) {
        alert( char ); // , et ensuite 
    }

    Appeler explicitement un itrateur

    Pour une comprhension plus approfondie, voyons comment utiliser explicitement un itrateur.

    Nous allons parcourir une chane de caractres de la mme manire que for..of, mais avec des appels directs. Ce code cre un itrateur de chane de caractres et en rcupre la valeur manuellement :

    let str = "Hello";
    
    // fait la mme chose que
    // for (let char of str) alert(char);
    
    let iterator = str[Symbol.iterator]();
    
    while (true) {
      let result = iterator.next();
      if (result.done) break;
      alert(result.value); // affiche les caractres un par un
    }

    Cela est rarement ncessaire, mais nous donne plus de contrle sur le processus que for..of. Par exemple, nous pouvons scinder le processus ditration : itrer un peu, puis arrter, faire autre chose, puis reprendre plus tard.

    Iterables et array-likes

    Il existe deux termes officiels qui se ressemblent mais qui sont trs diffrents. Assurez-vous de bien les comprendre pour viter la confusion.

    • Iterables sont des objets qui implmentent la mthode Symbol.iterator, comme dcrit ci-dessus.
    • Array-likes sont des objets qui ont des index et des length, ils ressemblent donc des tableaux.

    Lorsque nous utilisons JavaScript pour des tches pratiques dans un navigateur ou dautres environnements, il est possible que nous rencontrions des objets qui sont iterables ou des array-like, ou les deux.

    Par exemple, les chanes de caractres sont la fois iterables (for..of fonctionne dessus) et des array-likes (elles ont des index numriques et une longueur).

    Mais un itrable peut ne pas ressembler un array-like. Et inversement, un array-like peut ne pas tre itrable.

    Par exemple, la range dans lexemple ci-dessus est itrable, mais pas comme un array-like, car elle na pas de proprits indexes et de length.

    Et voici lobjet qui ressemble un tableau, mais pas itrable :

    let arrayLike = { // a des index et une longueur => semblable  un tableau
      0: "Hello",
      1: "World",
      length: 2
    };
    
    // Erreur (pas de Symbol.iterator)
    for (let item of arrayLike) {}

    Les iterables et les array-likes ne sont gnralement pas des tableaux, ils nont pas push, pop, etc. Cest plutt gnant si nous avons un tel objet et que nous voulons travailler avec lui comme avec un tableau. Par exemple, nous aimerions travailler avec une plage en utilisant les mthodes de tableau. Comment y parvenir ?

    Array.from

    Il existe une mthode universelle Array.from qui prend une valeur itrable ou array-like et en fait un vrai Array. Ensuite, nous pouvons appeler des mthodes de tableau dessus.

    Par exemple :

    let arrayLike = {
      0: "Hello",
      1: "World",
      length: 2
    };
    
    let arr = Array.from(arrayLike); // (*)
    alert(arr.pop()); // World (la mthode fonctionne)

    Array.from la ligne (*) prend lobjet, lexamine comme tant un objet itrable ou un array-like, cre ensuite un nouveau tableau et y copie tous les lments.

    Il en va de mme pour un itrable :

    // en supposant que cette "range" est tire de l'exemple ci-dessus
    let arr = Array.from(range);
    alert(arr); // 1,2,3,4,5 (array toString conversion fonctionne)

    La syntaxe complte de Array.from permet aussi de fournir une fonction optionnelle de mapping :

    Array.from(obj[, mapFn, thisArg])

    Le second argument mapFn peut tre une fonction appliquer chaque lment avant de lajouter au tableau, et thisArg permet den dfinir le this.

    Par exemple :

    // en supposant que cette "range" est tire de l'exemple ci-dessus
    
    // met au carr chaque nombre
    let arr = Array.from(range, num => num * num);
    
    alert(arr); // 1,4,9,16,25

    Ici, nous utilisons Array.from pour transformer une chane en un tableau de caractres :

    let str = '';
    
    // divise une chane en un tableau de caractres
    let chars = Array.from(str);
    
    alert(chars[0]); // 
    alert(chars[1]); // 
    alert(chars.length); // 2

    Contrairement str.split, il repose sur la nature itrable de la chane et donc, tout comme for..of, fonctionne correctement avec des paires de substitution.

    Techniquement, il fait la mme chose que :

    let str = '';
    
    let chars = []; // Array.from en interne fait la mme boucle
    for (let char of str) {
      chars.push(char);
    }
    
    alert(chars);

    Mais cest plus court.

    Nous pouvons mme crer une fonction slice qui prend en compte les paires de substitution :

    function slice(str, start, end) {
      return Array.from(str).slice(start, end).join('');
    }
    
    let str = '';
    
    alert( slice(str, 1, 3) ); // 
    
    // les mthodes native ne supporte pas les paires de substitution
    alert( str.slice(1, 3) ); // ordures (deux pices de paires de substitution diffrentes)

    Rsum

    Les objets pouvant tre utiliss dans for..of sappellent iterable.

    • Techniquement, les iterables doivent implmenter la mthode nomme Symbol.iterator.
      • Le rsultat de obj[Symbol.iterator]() sappelle un itrateur. Il gre le processus ditration ultrieur.
      • Un itrateur doit avoir la mthode nomme next() qui retourne un objet {done: Boolean, value: any}, ici done: true dnote la fin du processus de litration, sinon value est la valeur suivante.
    • La mthode Symbol.iterator est appele automatiquement par for..of, mais nous pouvons aussi le faire directement.
    • Les iterables intgrs tels que des chanes de caractres ou des tableaux implmentent galement Symbol.iterator.
    • Litrateur de chane de caractres connat les paires de substitution.

    Les objets qui ont des proprits indexes et des length sont appels array-like. De tels objets peuvent galement avoir dautres proprits et mthodes, mais ne possdent pas les mthodes intgres des tableaux.

    Si nous regardons lintrieur de la spcification nous verrons que la plupart des mthodes intgres supposent quelles fonctionnent avec des lments iterables ou des array-like au lieu de vrais tableaux, car cest plus abstrait.

    Array.from(obj[, mapFn, thisArg]) crer un vritable Array partir dun obj itrable ou array-like, et nous pouvons ensuite utiliser des mthodes de tableau sur celui-ci. Les arguments optionnels mapFn et thisArg nous permettent dappliquer une fonction chaque lment.

    Carte du tutoriel

    Commentaires

    lire ceci avant de commenter
    • Si vous avez des amliorations suggrer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
    • Si vous ne comprenez pas quelque chose dans l'article, merci de prciser.
    • Pour insrer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page