Vous êtes sur la page 1sur 58

IT ÉRATIONS, G ÉN ÉRATEUR, YIELD et NEXT

ES10 Itérateurs, Générateurs, &


Itérables

J AVA S C R I P T (Programmation Internet) V O L . V I

J.B. Dadet DIASOLUKA Luyalu Nzoyifuanga


+243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818

CHAPITRE 10 :
G ÉN ÉRATEUR, YIELD et NEXT :

Les générateurs sont des fonctions qu'on peut quitter


puis reprendre (continuer). Le contexte d'un
générateur (les liaisons avec ses variables) est
sauvegardé entre deux invocations. C’est donc aussi un
bon moyen d’utiliser des variables statiques dans
JavaScript, en plus des closures (fermetures, et
curries [currying ou Curryfication]).

Le corps d’une fonction génératrice function*


(« generator », notez l’astérisque) n'est pas exécuté
immédiatement lors de la création/définition d’une
variable, mais plutôt renvoie un objet ayant seulement
deux propriétés, la première ayant le nom « value » et
qui emmagasine la valeur retournée par yield, la
deuxième ayant le nom « done » qui indique si le
générateur est toujours actif (pas terminé).

La 1ère fois que la méthode « .next() » est appelé de


l’objet itérateur créé, le corps de la fonction génératrice
est exécuté de son début jusqu'à la première occurrence
de l’instruction yield rencontrée, qui définira la valeur à
renvoyer à l’objet itérateur qui l’aura appelé avec cette
instruction « .next ».

En fait tout se passe comme si (et c’est ainsi) « next »


parcourt l’un après l’autre les éléments de l’itérable en
incrémentant l’indexeur.

Illustration et comparaison :

I. VERSION STRING

<script type = "text/javascript"> "use strict";


const s = "diasoluka"; // Chaîne
let a = Array.from(s) , // Array
i = 0; // index
do {
console.log(`s : ${a[i++]}`)
} while (i < a.length);
</script>

<script type = "text/javascript"> "use strict";


console.log("=".repeat(15));
</script>

II. VERSION PROTOCOLES D'ITÉRATION

<script type = "text/javascript"> "use strict";


let alias;
const si = "diasoluka"; // Chaîne
var ii = si [Symbol.iterator]();
// Équivaut à
// let a = Array.from(s) , // Array
// ii = 0; // index

while(alias = ii.next() , ! alias.done){


console.log(`it = ${alias.value}`)
};
// Cette boucle while() équivaut à
// do {
// console.log(`s : ${a[i++]}`)
// } while (i < a.length);
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

</script>

N.B. : Un « objet itérateur » est créé sans l’opérateur


« new ».

Tout comme la commande return, la commande yield


renvoie une valeur de retour mais dans la propriété
.value de l’objet itérateur. La commande return quant à
elle renvoie la valeur de retour dans le propre type de
cette dernière.

Contrairement à return, yield ne clôt pas l’exécution de


la fonction génératrice mais la suspend seulement pour
être poursuivie à l’invocation de la prochaine méthode
.next(), qui exécutera jusqu’à la rencontre de la
prochaine instruction yield ou return.

<script>
function* repSces(obj) {
console.log("Avant yield");
yield obj;
}

let it = repSces(
console.log("Génération en cours"));

console.log("Appel à .next()");
console.log(`it.next()= `, it.next());
</script>

Itérateur–Générateur–Itérables -4/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

En simple, on peut dire que

1. yield est une sorte de return qui contrairement à ce


dernier ne clôt pas mais suspend/interrompt
l’exécution de la fonction génératrice. La valeur de
la propriété « générateur.done » demeure true.

2. return retourne aussi une valeur mais clôt le


générateur, la valeur de la propriété
« générateur.done » devenant false.

3. Cette fonction génératrice est définie avec le mot clé


iterator.

4. La méthode .next(), appelée pour la première fois,


exécute toute la fonction génératrice jusqu’à yield.
Itérateur–Générateur–Itérables -5/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
Les prochaines fois que .next() est appelée, elle
poursuit l’exécution de la fonction génératrice là où
yield l’avait suspendue.

5. Chaque appel à la méthode .next() doit avoir un yield


qui lui est associé dans le générateur. Une façon facile
de le garantir est d’utiliser une boucle valide qui
contient l’instruction yield. Pendant qu’on est dans
cette boucle yield renvoie une valeur valide, dès
qu’on quitte la boucle elle (yield) renvoie undefined,
à moins de prévoir des yield supplémentaire après et
en dehors de cette boucle.

6. Mais il n’est pas nécessaire (bien que souvent inutile)


d’avoir plus de yield dans le générateur que de
.next() appelées.

Itérateur–Générateur–Itérables -6/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
7. Un yield n’est pas obligé d’être dans une boucle.

8. Tout comme return, yield renvoie des valeurs de tout


type, pas seulement des booléennes, mais il (le yield)
n’est pas non plus obligé d’en renvoyer explicitement,
par exemple quand le .next() qui l’appelle utilise un
ou des arguments.

9. La valeur de retour de yield peut être utilisée « in


situ » [ex. console.log(yield)] ou être recueillie à
partir de la propriété .« value » de la méthode .next()
de l’obet générateur [ex. gen.next().value].

10. Comme yield ne clôt pas la fonction mais


seulement la suspend, les variables locales de la
fonction génératrice persistent donc après cette
suspension par yield.

En fait on peut comprendre la méthode « next » comme


demandant au « yield » d’envoyer la prochaine valeur de
retour.

11. La boucle « for…of » agit sur les « itérables »,


tandis que la boucle « for…in » agit sur les
« énumérables ».

Mais « yield » permet aussi de créer un objet


« itérable » :

<script type="text/javascript"> "use strict";


const iterable = {
*[Symbol.iterator]() {
yield "Date() = " + Date();
yield "Date.now() = " + Date.now();

Itérateur–Générateur–Itérables -8/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
yield "Math.PI = " + Math.PI;
yield "Math.E = " + Math.E;
}
};

for (let i of iterable) console.log(i);

console.log([...iterable])
</script>

Une autre façon légèrement différente d’écrire le code ci-


dessus :

<script type="text/javascript"> "use strict";


const iterable = new Object();

iterable[Symbol.iterator] = function* () {
yield "Date() = " + Date();
yield "Date.now() = " + Date.now();
yield "Math.PI = " + Math.PI;
yield "Math.E = " + Math.E;
};

for (let i of iterable) console.log(i);

Itérateur–Générateur–Itérables -9/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log([...iterable])
</script>

<script>
function* repSces(obj) {
const couples = Object.getOwnPropertyNames(obj);
// ou
// const couples = Reflect.ownKeys(obj);

for (const cle of couples) yield [cle, obj[cle]];


}

// Les couples [cle,val] ds chaque objet-membre


// de l'Array diags
const diags = [
{ nom: 'Likelele', sce: "Ophtalmo", path: "Cata-
racte" },
{ nom: 'Monzele', sce: "Gynéco", path: "Leucor-
rhée" },
{ nom: 'Ntaba', sce: "Vétérinaire", path: "Rage" }
];

let c=0;

while(c < diags.length){


Itérateur–Générateur–Itérables -10/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

// Retourner un itérable pour chaque membre de


diags.
for (const [id,svce] of repSces(diags[c++])) {

// Retourner [cle,val] pour chaque couple d'un


// membre de diags.
console.log(`${id}: ${svce}`);

}
console.log(`${"=".repeat(20)}`);
}
</script>

Une extension de ce qui précède :

I. Tous les traitements faits dans «


*[Symbol.iterator]() {}
»

<script type="text/javascript"> "use strict";


let flagt=0, flagc=0, c=0,
m = ["carie","parodontite","tartre","gingivite"];

Itérateur–Générateur–Itérables -11/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
const it = {
*[Symbol.iterator]() {
for(let k of m) {
if(k=="tartre") flagt++;
if(k=="crouzon") flagc++;
yield ++c+". "+k;
}
}
}

for (let i of it) console.log(i);

if(flagt)console.log("tartre était là");

if(flagc)console.log("Crouzon était là");


else console.log("Crouzon n'était pas là");
</script>

II. Tous les traitements faits en dehors «


*[Symbol.iterator]() {}
», avec quelques modifications aussi :

<script type="text/javascript"> "use strict";


let flagt=0, flagc=0, c=-2,
m = ["carie","tartre","parodontite","gingivite"];

const it = {
*[Symbol.iterator]() {
for (let k of m) yield c+=2;
}
}

for (let i of it){


Itérateur–Générateur–Itérables -12/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
if(m[i]=="tartre") flagt++;
if(m[i]=="crouzon") flagc++;
console.log(m[i]);
}
if(flagt)console.log("tartre était retenue");
else console.log("tartre n'était pas retenue");

if(flagc)console.log("Crouzon était là");


else console.log("Crouzon n'était pas là");
</script>

Un exemple pratique de la boucle itératrice « for…


of » :
Toutes les combinaisons 3 à trois des éléments de 3
Arrays de n’importe quelle taille :

<script type="text/javascript"> "use strict";


const a1 = [3, 1, 6, 7],
a2 = [8, 5, 0],
a3 = [2, 4, 9, 5, 1];

let combo = [], t="";


for (let x of a1) for (let y of a2) for (let z of a3)
combo.push([x , y , z]);

let cptr=0;
for (let v of combo)
t += (++cptr).toString().padStart(2,'.') + ") " +
v+' | ';
console.log(t);
</script>

Itérateur–Générateur–Itérables -13/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

Voici en clair comment s’est fait et comment doit se faire


facilement l’indexation même manuellement :

<script type="text/javascript"> "use strict";


const a1 = [0, 1, 2, 3],
a2 = [0, 1, 2, 3],
a3 = [0, 1, 2, 3];

let combo = [], t="";


for (let x of a1) for (let y of a2) for (let z of a3)
combo.push([x , y , z]);

let cptr=0;
for (let v of combo)
t += (++cptr).toString()
.padStart(2,String
.fromCharCode(183)) +
") " +
v+' | ';
console.log(t);
</script>

Itérateur–Générateur–Itérables -14/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

Et avec des lettres :

<script type="text/javascript"> "use strict";


const a1 = ["L", "U", "Y"],
a2 = ["L", "U", "Y"],
a3 = ["L", "U", "Y"];

let combo = [], t="";


for (let x of a1) for (let y of a2) for (let z of a3)
combo.push([x , y , z]);

let cptr=0;
for (let v of combo)
t += (++cptr).toString()
.padStart(2,String
.fromCharCode(183)) +
") " +
v+' | ';
console.log(t);
</script>

Itérateur–Générateur–Itérables -15/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

Syntaxe de base d’une fonction génératrice :

Déclaration de la fonction-génératrice :

function* genFct(){ // Notez l’astérisque *


var idx = 0;
while (idx <= lim) // test de la condition
yield idx++; // operation et ret value
}

Appel de la fonction itératrice :

L’appel à une fonction génératrice ne l’exécute pas


(n’exécute pas son corps), mais crée un objet
« itérateur » qui permettra de contrôler ce corps de la
fonction. Notez ici qu’on crée l’objet itérateur sans
l’opérateur « new ».

let it = genFct(); // Défnition de l’itérateur


// = création de l'objet itérateur « it ».

it.next(); // Appel du premier yield via « it »


it.next(); // Appel du prochain yield "
it.next(); // Appel du prochain yield "
it.next(); // Appel du prochain yield "

Itérateur–Générateur–Itérables -16/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

Exemple :

<script type="text/javascript"> "use strict";


let cl = console.log;

// Définition d'un générateur avec *


function* fGenerator() {
let current = 9;
while (true) { // Boucle Indispensable
yield current++;
}
yield;
} // Fin Définition du générateur

const it = fGenerator();
// Déf itérateur par appel au générateur

cl(it.next().value); // 9
cl(it.next().value); // 10

cl(it.next().value.toString(2), " base 2"); // 1011


cl(it.next().value.toString(4), " base 4"); // 30
cl(it.next().value.toString(8), " base 8"); // 15
cl(it.next().value.toString(10), " base 10"); // 14
cl(it.next().value.toString(15), " base 15"); // 10
cl(it.next().value.toString(16), " base 16"); // 10
</script>

Pour le cas ci-dessus, à la place de « while ( true ) » on


peut utiliser « for ( ; ; ) » ou « do {...} while ( true ) »,
et à la place de true on peut utiliser n’importe quel test
conditionnel valide :

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var index = 0;
do{
yield index++;

Itérateur–Générateur–Itérables -17/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// prochaine instruction = do{}, tant que
// la condition de la boucle est remplie.
} while(index < 3)

console.log("1er next Après la boucle")


// Ne sera exécuté qu'une seule fois quand
// la condition de la boucle n’est plus remplie,
// avant le yield (return du generator) du
// premier next quand on quitte la boucle.
} // Fin function* numeroter()

var it = numeroter();

console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().value); // 1er next Après la boucle
console.log(it.next().value); // undefined
console.log(it.next().value); // undefined
</script>

Une autre version de ça :

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var index = 0;
do{
yield index++;
} while(index < 12);

console.log("1er next Après la boucle")


} // Fin function* numeroter()

const nc = [
"I = OLFACTIF, Se", "II = OPTIQUE, SDe",
"III = OCULO-MOTEUR COMMUN (innerve tous les "+
"autres muscles extrinsèques, la musculature "+
"intrinsèque [muscle ciliaire {accommodation} "+
"et sphincter de l'iris], et le releveur de "+
"paupière supérieure), Mo",
"IV = PATHÉTIQUE (=trochléaire. Innerve le "+
"grand oblique), Mo", "V = TRIJUMEAU, Mi",
Itérateur–Générateur–Itérables -18/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
"VI = OCULO-MOTEUR EXTERNE (=abducens. "+
"Innerve le droit externe), Mo",
"VII = FACIAL (Mi)",
"VIII = VESTIBULO-COCHLÉAIRE, Se",
"IX = GLOSSO-PHARYNGIEN, Mi",
"X = PNEUMOGASTRIQUE (=Vague), Mi",
"XI = SPINAL (=accessoire), Mi",
"XII = GRAND HYPOGLOSSE, Mi."
];
var it = numeroter();

do{
var c = it.next().value;
console.log(`* ${c+1}è paire => ${nc[c]}`);
}
while(nc[c]!=="XII = GRAND HYPOGLOSSE, Mi.");
</script>

Et avec la boucle « for ... in » :

Itérateur–Générateur–Itérables -19/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
<script type="text/javascript"> "use strict";
function* numeroter(){ // Constructeur
var idx = [0,10,20,30];
for (let k in idx) {// prochaine instruction = for{
yield idx[k];
}
// 0 10 20 30 undefined
}

var it = numeroter();

console.log(it.next().value); // 0
console.log(it.next().value); // 10
console.log(it.next().value); // 20
console.log(it.next().value); // 30
console.log(it.next().value); // undefined
</script>

Quand on quitte la boucle de la fonction génératrice,


celle-ci ne se clôt pas, mais le yield renvoie alors
undefined.

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var idx = [0,20,10,30];
for (let k in idx) {
yield idx[k]>15;
}
// false true false true undefined
}

var it = numeroter();

console.log(it.next().value); // false
console.log(it.next().value); // true
console.log(it.next().value); // false
console.log(it.next().value); // true
console.log(it.next().value); // undefined
</script>

. next() exécute toujours, et


Itérateur–Générateur–Itérables -20/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
yield retourne une valeur de n’importe quel type, dans la
propriété « value » de l’itérateur.

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var diag = {
Conjonctivite:"sécrétions",
Myopie:"lunettes",
Rétinoblastome:"masse",
Perforation:"herniation"
},
// Object literal ([définition] littéral d’objet).

ard=[
"Conjonctivite",
"Myopie",
"Rétinoblastome",
"Perforation"
];

for (let idx=0;;idx++) {


yield diag[ard[idx]];
}
// sécrétions lunettes masse herniation un-
defi-ned
}

var it = numeroter();

console.log(it.next().value); // sécrétions
console.log(it.next().value); // lunettes
console.log(it.next().value); // masse
console.log(it.next().value); // herniation
console.log(it.next().value); // undefined
console.log(it.next().value); // undefined
</script>

Une autre façon d’écrire ce même code :

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur

Itérateur–Générateur–Itérables -21/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
var index = 0;
do{
yield index++;
// prochaine instruction = do{}, tant que
// la condition de la boucle est remplie.
} while(index < 3)

console.log("1er next Après la boucle")


// 1er next Après la boucle
//
// Ne sera exécuté qu'une seule fois quand
// la condition de la boucle n’est plus remplie,
// avant le yield (return du generator) du
// premier next quand on quitte la boucle.
} // Fin function* numeroter()

var it = numeroter();

const diag = {
Conjonctivite:"sécrétions",
Myopie:"lunettes",
Rétinoblastome:"masse",
Perforation:"herniation"
};

let c;
c = it.next().value;
console.log(Object.entries(diag)[c][0],
Object.entries(diag)[c][1]);
// Conjonctivite sécrétions

c = it.next().value;
console.log(Object.entries(diag)[c][0],
Object.entries(diag)[c][1]);
// Myopie lunettes

c = it.next().value;
console.log(Object.entries(diag)[c][0],
Object.entries(diag)[c][1]);
// Rétinoblastome masse

c = it.next().value;

Itérateur–Générateur–Itérables -22/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log(Object.entries(diag)[c][0],
Object.entries(diag)[c][1]);
// TypeError:
// Object.entries(...)[c] is undefined;
// can't access element at index 0
</script>

La méthode .next() du générateur :

La méthode .next() renvoie un objet dont :


1. La propriété value contient la valeur générée (par
yield) et peut être manipulée librement.
2. Une propriété done qui indique si la boucle de la
fonction génératrice est toujours active, donc si le
générateur a ou pas produit sa dernière valeur soit-elle
valide ou pas même quand la valeur retournée est
undefined.

AFFICHAGE DIRECT DE LA STRUCTURE INTERNE DE


L’OBJET GÉNÉRATEUR :

<script type="text/javascript"> "use strict";


function* Generator() {
yield "Valeur retournée par yield";
}

var gen = Generator();


var r;
r=gen.next();

console.log(r);

// Object {
// value: "Valeur retournée par yield",
// done: false
// }

Itérateur–Générateur–Itérables -23/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
//
//
// {…}
// done: false
// value: "Valeur retournée par yield"
// <prototype>: Object { … }

</script>

AFFICHAGE VIA Object.getOwnPropertyDescriptors(yield


retval) :

<script type="text/javascript"> "use strict";


function* Generator() {
yield "Valeur retournée par yield";
}

var gen = Generator();


var r;
r=gen.next();

console.log(Object.getOwnPropertyDescriptors(r))

// DANS CONSOLE DE FIREFOX 62.0.2 :


//
// Object { value: {…}, done: {…} }
//
// 1er niveau de détails (Firefox) :
//
// {…}
// done: Object {
// value: false,
// writable: true,
// enumerable: true, …
// }
// value: Object {
// value: "Valeur retournée par yield",
// writable: true,
// enumerable: true, …

Itérateur–Générateur–Itérables -24/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// }
// <prototype>: Object { … }
//
//
// 2e niveau de détails (Firefox) :
//
// done: {…}
// configurable: true
// enumerable: true
// value: true
// writable: true
// <prototype>: Object { … }
// value: {…}
// configurable: true
// enumerable: true
// value: undefined
// writable: true
// <prototype>: Object { … }
// <prototype>: Object { … }
//
//

// DANS CONSOLE DE YANDEX Version 18.10.1.385 beta


//
// {value: "Valeur retournée par yield", done: false}
// {value: {…}, done: {…}}
//
// 1er niveau de détails (Yandex) :
//
// done: {
// value: false,
// writable: true,
// enumerable: true,
// configurable: true
// }
// value: {
// value: "Valeur retournée par yield",
// writable: true,
// enumerable: true,
// configurable: true
// }
// __proto__: Object

Itérateur–Générateur–Itérables -25/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
//
//
// 2e niveau de détails (Yandex) :
//
// done:
// configurable: true
// enumerable: true
// value: false
// writable: true
// __proto__: Object
// value:
// configurable: true
// enumerable: true
// value: "Valeur retournée par yield"
// writable: true
// __proto__: Object
// __proto__: Object
</script>

AFFICHAGE VIA Object.getOwnPropertyNames(yield


retval) :

<script type="text/javascript"> "use strict";


function* Generator() {
yield "Valeur retournée par yield";
}

var gen = Generator();


var r;
r=gen.next();

console.log(Object.getOwnPropertyNames(r))

// DANS CONSOLE DE FIREFOX 62.0.2 :


//
// Array [ "value", "done" ]
//
// Un seul (1er) niveau de détails (Firefox) :
//

Itérateur–Générateur–Itérables -26/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// (2) […]
// 0: "value"
// 1: "done"
// length: 2
// <prototype>: Array []
//
//

// DANS CONSOLE DE YANDEX Version 18.10.1.385 beta


//
// (2) ["value", "done"]
//
// Un seul (1er) niveau de détails (Yandex) :
//
// (2) ["value", "done"]
// 0: "value"
// 1: "done"
// length: 2
// __proto__: Array(0)

</script>

Les propriétés « value » et « done » de l’objet retourné


par yield sont utilisées comme celles de tout autre objet
(obj.prop).

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var diag = {
Conjonctivite:"sécrétions",
Myopie:"lunettes",
Rétinoblastome:"masse",
Perforation:"herniation"
},
// Object literal ([définition] littéral d’objet).

ard=[
"Conjonctivite",
"Myopie",
"Rétinoblastome",

Itérateur–Générateur–Itérables -27/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
"Perforation"
];

for (let idx=0;;idx++) {


yield diag[ard[idx]];
}
// sécrétions lunettes masse herniation undefi-
ned
}

var gen = numeroter();

let r;
r=gen.next();
console.log(r.value + " " + r.done); // sécrétions false
r=gen.next();
console.log(r.value + " " + r.done); // lunettes false
r=gen.next();
console.log(r.value + " " + r.done); // masse false
r=gen.next();
console.log(r.value + " " + r.done); // herniation false
r=gen.next();
console.log(r.value + " " + r.done); // undefined false
r=gen.next();
console.log(r.value + " " + r.done); // undefined false
</script>

La valeur generator.done du générateur devient true


dès qu’on a fini avec le générateur :

1er exemple :

<script type="text/javascript"> "use strict";


var r;
function* idMaker() {
var index = 2;
while (Math.abs(index) < Math.abs(index+1))
yield index--;
}

var gen = idMaker();

Itérateur–Générateur–Itérables -28/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

r=gen.next(); console.log(r.value , r.done); // 2 false


r=gen.next(); console.log(r.value , r.done); // 1 false
r=gen.next(); console.log(r.value , r.done); // 0 false
r=gen.next(); console.log(r.value , r.done); // undefined
true
r=gen.next(); console.log(r.value , r.done); // undefined
true
r=gen.next(); console.log(r.value , r.done); // undefined
true
</script>

2e exemple :

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var index = 0;
do{
yield index++;
// prochaine instruction = do{}, tant que
// la condition de la boucle est remplie.
} while(index < 3)

console.log("1er next Après la boucle")


// Ne sera exécuté qu'une seule fois quand
// la condition de la boucle n’est plus remplie,
// avant le yield (return du generator) du
// premier next quand on quitte la boucle.
} // Fin function* numeroter()

var gen = numeroter();

let r;
r=gen.next();
console.log(r.value+" "+r.done); // 0 false
r=gen.next();
console.log(r.value+" "+r.done); // 1 false
r=gen.next();
console.log(r.value+" "+r.done); // 2 false
r=gen.next();
console.log(r.value+" "+r.done);
// 1er next Après la boucle
Itérateur–Générateur–Itérables -29/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// undefined
r=gen.next();
console.log(r.value+" "+r.done); // undefined true
r=gen.next();
console.log(r.value+" "+r.done); // undefined true

// 0 false test.html:21:1
// 1 false test.html:23:1
// 2 false test.html:25:1
// 1er next Après la boucle test.html:10:3
// undefined true test.html:27:1
// undefined true test.html:29:1
// undefined true test.html:31:1
</script>

Ci-dessous aussi, on quitte la boucle quand idx atteint ou


dépasse 3 [ for (let idx=0;idx<3;idx++) ]. En ce moment-
là aussi, generator.done est devenu true.

<script type="text/javascript"> "use strict";


function* numeroter(){ // Constructeur
var diag = {
Conjonctivite:"sécrétions",
Myopie:"lunettes",
Rétinoblastome:"masse",
Perforation:"herniation"
},
// Object literal ([définition] littéral d’objet).

ard=[
"Conjonctivite",
"Myopie",
"Rétinoblastome",
"Perforation"
];

for (let idx=0;idx<3;idx++) {


yield diag[ard[idx]];
}
// sécrétions false, lunettes false, masse false
// undefined true, undefined true, undefined true

Itérateur–Générateur–Itérables -30/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
}

var gen = numeroter();

let r;
r=gen.next();
console.log(r.value + " " + r.done); // sécrétions false
r=gen.next();
console.log(r.value + " " + r.done); // lunettes false
r=gen.next();
console.log(r.value + " " + r.done); // masse false
r=gen.next();
console.log(r.value + " " + r.done); // undefined true
r=gen.next();
console.log(r.value + " " + r.done); // undefined true
r=gen.next();
console.log(r.value + " " + r.done); // undefined true

// sécrétions false test.html:28:1


// lunettes false test.html:30:1
// masse false test.html:32:1
// undefined true test.html:34:1
// undefined true test.html:36:1
// undefined true test.html:38:1
</script>

Passation d’arguments à la fonction génératrice :


On peut passer des arguments à la fonction génératrice
lors de sa définition. Ces arguments se comportent dans
la fonction génératrice exactement comme les
paramètres des fonctions ordinaires. [En passant
signalons que comme d’habitude, il est recommandé de
ne jamais modifier la valeur de ces paramètres (mais on
peut le faire si on veut) ; au besoin on ferait mieux
d’affecter leurs valeurs à des variables locales].

<script type="text/javascript"> "use strict";


var v;
function* generator(g,p) {// Constructeur
Itérateur–Générateur–Itérables -31/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log("Exécution du 1er yield")
yield ; // retourne undefined

console.log("Exécution du 2e yield")
yield g;

console.log("Exécution du 3e yield")
yield g + v;

console.log("Exécution du 4e yield")
yield p + v;

console.log("Exécution du 5e yield")
yield g * p + v;
}

var gen = generator(5,10);


console.log("Après définition du générateur");

v = 7; // Et/ou autres instructions...


console.log(gen.next().value); // undefined

v = 15;
console.log(gen.next().value); // 5

v = 25;
console.log(gen.next().value); // 30

v = 30;
console.log(gen.next().value); // 40

v = 40;
console.log(gen.next().value); // 90

console.log(gen.next().done) // true

// RÉSULTATS

// Après définition du générateur test.html:21:3


// Exécution du 1er yield test.html:4:6
// undefined test.html:24:3

Itérateur–Générateur–Itérables -32/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

// Exécution du 2e yield test.html:7:6


// 5 test.html:27:3

// Exécution du 3e yield test.html:10:6


// 30 test.html:30:3

// Exécution du 4e yield test.html:13:6


// 40 test.html:33:3

// Exécution du 5e yield test.html:16:6


// 90 test.html:36:3

// true test.html:38:3
</script>

L’appel de la méthode .next() avec un argument


reprendra l'exécution de la fonction génératrice, comme
d’habitude là où elle s’était interrompue, et cet argument
deviendra la valeur de retour de yield (remplacera la
valeur de l'expression yield sans rien d’autre) mais à
utiliser in situ (inline) : cet argument de .next() passé
au générateur n’est pas retournée dans la propriété
value de l’objet générateur. Vérifiez ci-dessous l’ordre
d’exécution dans l’affichage de la console, et notez que
l’argument du premier « appel au générateur avec
argument » (« 1. Keliol ») n’a pas été utilisé (n’est pas
affiché).

<script type="text/javascript"> "use strict";


function* Generator() {
console.log("0è instructions suite...");
yield "Depuis le générateur";

console.log("*** 1ère Série d'instructions...");


console.log(yield);

console.log("*** 2ès instructions");


Itérateur–Générateur–Itérables -33/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
yield;

console.log("*** 3ès instructions");


console.log(yield);

console.log("*** 4ès instructions");


console.log(yield);

console.log("*** 5ès instructions");


console.log(yield);

console.log("*** 6ès instructions");


console.log(yield);
}

var gen = Generator();

// yield récupère automatiquement les arguments.


console.log(gen.next().value);
console.log(gen.next()('1. Keliol').value);
console.log(gen.next()('2. Baron').value);
console.log(gen.next()('3. Petrosa').value);
console.log(gen.next()('4. Kelantina').value);
</script>

Exécution :

0è instructions suite... test.html:3:3


Depuis le généérateur test.html:28:4
*** 1ère Série d'instructions... test.html:6:3
undefined test.html:29:4
2. Baron test.html:7:3
*** 2ès instructions test.html:9:3
undefined test.html:30:4
*** 3ès instructions test.html:12:3
undefined test.html:31:4
4. Kelantina test.html:13:3
*** 4ès instructions test.html:15:3
undefined test.html:32:4

Itérateur–Générateur–Itérables -34/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
L’instruction return dans un générateur termine le
générateur (done devenant true). La valeur renvoyée
par return sera la valeur de terminaison du générateur.
Une fois un générateur terminé, il ne peut plus produire
d'autres valeurs.

<script type="text/javascript"> "use strict";


var r;
function* Generator() {
console.log("*** 1ère Série d'instructions");

console.log("^^^^^^^",yield "Initio");
// Exécute d'abord yield (donc rentre vers le next
appelant),
// et donc interrompt et quitte le générateur sans le
fermer,
// et donc le console.log() ci-dessus
// sera exécuté seulement au prochain .next(), mais
// pas avec la valeur en cours de yield ("Initio"), mais
// ave l'argument éventuel du .next() suivant ("2.
Keliol...").
// Voir l'ordre d'exécution dans l'affichage de la
console.

console.log("*** 2ès instructions");


console.log("^^^^^^^",yield);

console.log("*** 3ès instructions");


return 45;

// unreachable code after return statement test.html:10:5

console.log("*** 4ès instructions");


console.log(yield);

console.log("*** 5ès instructions");


console.log(yield);

console.log("*** 6ès instructions");


console.log(yield);

Itérateur–Générateur–Itérables -35/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
}

var gen = Generator();

r=gen.next();
console.log("=>",r,r.value,r.done," <=");

// yield récupère automatiquement les arguments de


.next().

r=gen.next()('2. Keliol [2è next]');


console.log(r,r.value,r.done);

r=gen.next()('3. Baron [3è next]');


console.log(r,r.value,r.done);

r=gen.next()('4. Petrosa [4è next]');


console.log(r,r.value,r.done);
// value = 45 , done = true

r=gen.next()('5. Kelantina [5è next]');


console.log(r,r.value,r.done);

console.log("Les autres instructions exécutent...");

// *** 1ère Série d'instructions


// test.html:4:6
// => Object { value: "Initio", done: false } Initio false
<=
// test.html:38:4
// ^^^^^^^ 2. Keliol [2è next]
// test.html:6:6
// *** 2ès instructions
// test.html:16:6
// Object { value: undefined, done: false } undefined
false
// test.html:43:6
// ^^^^^^^ 3. Baron [3è next]
// test.html:17:6
// *** 3ès instructions

Itérateur–Générateur–Itérables -36/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// test.html:19:6
// Object { value: 45, done: true } 45 true
// test.html:46:10
// Object { value: undefined, done: true } undefined true
// test.html:49:6
// Object { value: undefined, done: true } undefined true
// test.html:53:6
// Les autres instructions exécutent...
// test.html:55:4
// unreachable code after return statement [En savoir
plus]
// test.html:24:5
</script>

Tentative de l’explication de l’Ordre d’exécution du code


ci-dessus :

1. var gen = Generator();


Définition du générateur.
2. r=gen.next();
Demande d’exécuter le générateur jusqu’au
premier yield y rencontré, ce qui poussera yield à
renvoyer une valeur de retour à ce .next(), puis
suspendre immédiatement l’exécution du
générateur (pour notre cas ici même l’exécution du
reste du console.log) et continuer l’exécution
exactement à l’endroit où .next() l’a envoyée vers
le générateur. L’exécution du programme s’y
poursuivra jusqu’à rencontrer éventuellement le
prochain .next() qui la redirigera de nouveau vers
le générateur, exactement là où elle s’y est
interrompue. Pour notre cas présent le programme
reprendra l’exécution de

« console.log ( " ^^^^^^^ " , yield " Initio " ) ; »,

c’est-à-dire d’abord la chaîne " ^^^^^^^ " puis la valeur


Itérateur–Générateur–Itérables -37/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
proposée à yield, mais ce paramètre n’est plus le
même et vaut maintenant la valeur de l’argument
du .next() en cours (le deuxième .next()) et qui
est :
« '2 . Keliol [2è next ] ' »

3. Jusque-là le programme aura donc exécuté et affiché :

console.log ( " *** 1ère Série d'instructions " ) ;

=> *** 1ère Série d'instructions test.html:4:6

et retourné un objet générateur avec


« value="Initio" » à l’instruction

console.log ( " => " , r , r . value , r . done , " <= " ) ;

qui se trouve dans l’appelant et aura affiché :


=> Object { value: " Initio " , done: false } Initio false <= test.html:38:4

4. Le programme poursuivra son exécution normale dans


l’appelant, jusqu’au prochain .next() (le deuxième)
dans l'instruction ci-dessous :
r = gen . next ( ' 2. Keliol [ 2è next ] ' ) ;

À ce niveau-là le programme interrompra encore sa file


dans l’appelant pour se rendre dans le générateur là
où elle l’a quittée, pour y continuer son exécution,
c’est-à-dira la suite de l’affichage de l’instruction

« console . log ( yield ) ; » ,

avec les nouveaux paramètres de yield : « ‘2 . Keliol [


2è next ] ' ». Le programme y poursuivra l’exécution
de la console qu’elle avait abandonnée, mais avec les

Itérateur–Générateur–Itérables -38/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
paramètres en cours, ce qui affichera
^^^^^^^ 2. Keliol [2è next] test.html:6:6.

5. Le programme poursuit par la suite son exécution dans


le générateur jusqu’au prochain yield ou return. Il
croise dans l’entretemps l’instruction

console . log ( " *** 2ès instructions " ) ;

qu’il exécute en affichant :

*** 2ès instructions test.html:16:6

Cette instruction étant une ordinaire, le programme se


poursuit jusqu’au

console.log(yield);

Pendant l’exécution de cette dernière instruction


(console.log(yield)), le programme exécutera
naturellement d’abord l’argument de l’instruction
c’est-à-dire le yield, qui retournera au générateur à
l’objet générateur le paramètre du .next() qui a
appelé son générateur, et qui devrait être affichée
avec l’instruction ci-dessous :

Console . log ( r , r . value , r . done ) ;

pour afficher :

Object { value : undefined , done : false } undefined false test.html:43:6

6. Le programme poursuit son exécution dans l’appelant


jusqu’au prochain .next() (le troisième) :

Itérateur–Générateur–Itérables -39/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

r = gen . next ( ' 3 . Baron [ 3è next ] ' ) ;

Le programme rentre donc dans le générateur


exactement là où il l’a quitté, c’est-à-dire à
l’instruction

console . log ( " ^^^^^^^ " , yield ) ;

Là, il continue l’affichage qu’il avait interrompu,


comme expliqué plus haut, avec une nouvelle données
pour yield (l’argument du .next() en cours), qui est :

' 3. Baron [ 3è next ] '

pour afficher :

^^^^^^^ 3. Baron [3è next] test.html:17:10

Il y continue jusqu’à rencontrer le prochain yield,


c’est-à-dire exécute d’abord

console . log ( " *** 3ès instructions " ) ;

en affichant

*** 3ès instructions test.html:19:6

puis continue jusqu’à rencontrer return qui clôt le


générateur, tout en renvoyant la valeur arbitraire 45,
comme ceci :

return 45;

Itérateur–Générateur–Itérables -40/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
7. Le programme rentre donc dans l’appelant en
renvoyant la valeur 45 à l’objet générateur dans
l’appelant, pour y exécuter l’instruction

console . log ( r , r . value , r . done ) ;

qui affiche :

Object { value: 45, done: true } 45 true test.html:46:6

indiquant aussi, avec la valeur,, que le générateur qui


jusque-là était actif, est maintenant clos :

gen . done == true .

Yield avec astérisque (yield*) :

Avec yield* (yield avec astérisque) la génération des


valeurs est déléguée à une autre fonction génératrice.

<script type="text/javascript"> "use strict";


var r;
function* autreGen(i) {
yield i * 2; // pour *B*, retourne 30 = 15*2
yield i * 3; // pour *C*, retourne 45 = 15*3
yield i * 4; // pour *D*, retourne 60 = 15*4
}

var agen = autreGen(5);

function* gen(i){
yield i; // Retourne 15 pour *A* seulement
yield* autreGen(i);
// délègue à yield* pour *B*, *C* et *D*
// (puisque 3 yield ds autreGen),
// avec i=15 (argument de yield*)
Itérateur–Générateur–Itérables -41/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

console.log("agen*** ",agen.next().value); // agen***


10
// 1er appel direct, donc 1er yiedl autreGen 10 = 5*2

yield i * 6;
// Suite des yield dans gen, donc retourne 15*6 pour *E*

yield i * 7;
// Retourne 15*7=105 pour *F*
}

var gen = gen(15); // i ds gen = 15

r=gen.next();
console.log("A**gen ",r.value,r.done); // A**gen 15
false

r=gen.next();
console.log("B**gen ",r.value,r.done); // B**gen 30
false

r=gen.next();
console.log("C**gen ",r.value,r.done); // C**gen 45
false

r=gen.next();
console.log("D**gen ",r.value,r.done); // D**gen 60
false

r=gen.next();
console.log("E**gen ",r.value,r.done); // E**gen 90
false

r=gen.next();
console.log("F**gen ",r.value,r.done); // F**gen 105
false

r=gen.next();
console.log("F**gen ",r.value,r.done); // F**gen
undefined true

Itérateur–Générateur–Itérables -42/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// undefined : il n'y a plus de yield dans gen.
</script>

On ne peut pas utiliser l’opérateur « new » avec les


générateurs. On dit qu’ils ne sont pas constructibles.

<script type="text/javascript"> "use strict";


function* f() {}
var obj = new f;
// TypeError: f n'est pas un constructeur
</script>

Application :

Génération aléatoire d’IMC en fonction de poids et tailles


générés aléatoirement :

<script type="text/javascript"> "use strict";


function* Generator() {
let n=0;
while(true){
var ech={
p : Math.round(Math.random()*60+20),
t : Math.round(Math.random()*120+80)
},
imc = ech["p"] * ech["p"] / ech["t"];

yield String(++n).padStart(2,'.')+
". pds=" + String(ech["p"]).padStart(3,' ')
+
" kg , taille=" +
String(ech["t"]).padStart(4,' ')+
" cm , imc=" + imc.toPrecision(4) + "
kg²/cm" ;
}
}

var gen = Generator();

Itérateur–Générateur–Itérables -43/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

for(let k=0 ; k<20 ; k++){


var r = gen.next();
console.log(r.value);
}
</script>

Exéccution :

.1. pds= 79 kg , taille= 198 cm , imc=31.52 kg²/cm test.html:23:7


.2. pds= 53 kg , taille= 127 cm , imc=22.12 kg²/cm test.html:23:7
.3. pds= 26 kg , taille= 89 cm , imc=7.596 kg²/cm test.html:23:7
.4. pds= 26 kg , taille= 95 cm , imc=7.116 kg²/cm test.html:23:7
.5. pds= 34 kg , taille= 184 cm , imc=6.283 kg²/cm test.html:23:7
.6. pds= 26 kg , taille= 180 cm , imc=3.756 kg²/cm test.html:23:7
.7. pds= 63 kg , taille= 153 cm , imc=25.94 kg²/cm test.html:23:7
.8. pds= 64 kg , taille= 109 cm , imc=37.58 kg²/cm test.html:23:7
.9. pds= 22 kg , taille= 124 cm , imc=3.903 kg²/cm test.html:23:7
10. pds= 74 kg , taille= 88 cm , imc=62.23 kg²/cm test.html:23:7
11. pds= 41 kg , taille= 182 cm , imc=9.236 kg²/cm test.html:23:7
12. pds= 28 kg , taille= 119 cm , imc=6.588 kg²/cm test.html:23:7
13. pds= 34 kg , taille= 171 cm , imc=6.760 kg²/cm test.html:23:7
14. pds= 46 kg , taille= 176 cm , imc=12.02 kg²/cm test.html:23:7
15. pds= 58 kg , taille= 192 cm , imc=17.52 kg²/cm test.html:23:7
16. pds= 36 kg , taille= 190 cm , imc=6.821 kg²/cm test.html:23:7
17. pds= 77 kg , taille= 163 cm , imc=36.37 kg²/cm test.html:23:7
18. pds= 43 kg , taille= 177 cm , imc=10.45 kg²/cm test.html:23:7
19. pds= 51 kg , taille= 149 cm , imc=17.46 kg²/cm test.html:23:7
20. pds= 29 kg , taille= 181 cm , imc=4.646 kg²/cm test.html:23:7

Array de valeurs générées :

<script type="text/javascript"> "use strict";


const obj = {
*[Symbol.iterator]() {
const max = 10;
for (let i = 1; i <= max; i++) {
yield i+". "+ Math.pow(2,i);
}
}
};

Itérateur–Générateur–Itérables -44/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
for (let member of obj) {
console.log(member);
}
</script>

Exécution :

1. 2 test.html:12:3
2. 4 test.html:12:3
3. 8 test.html:12:3
4. 16 test.html:12:3
5. 32 test.html:12:3
6. 64 test.html:12:3
7. 128 test.html:12:3
8. 256 test.html:12:3
9. 512 test.html:12:3
10. 1024 test.html:12:3

En matière de table d’exposents de 2, voici comment on


peut encore mieux le faire avec le CURRYING :

https://gist.github.com/kavitshah8/d8ba19d09334d8e08a
1f209fdbacb597/raw/d96f9bab8f5fbbf5b4d9227f48c73a6
848525524/curry2.js

<script type="text/javascript"> "use strict";


function pow2x (a) {
return Math.pow(2,a);
}

function compound (f) {


return function (b) {
return f(f(b))
}
}

for(let k=0;k<=10;k++){
console.log(2,"^",k,"=", pow2x(k) )
}

console.log("")
Itérateur–Générateur–Itérables -45/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

var p=1;
for(let k=0;k<=10;k++){
var res=compound(pow2x)(k)
console.log(p,"^",2,"=", compound(pow2x)(k) )
p=res
}

// 2 ^ 0 = 1 test.html:12:23
// 2 ^ 1 = 2 test.html:12:23
// 2 ^ 2 = 4 test.html:12:23
// 2 ^ 3 = 8 test.html:12:23
// 2 ^ 4 = 16 test.html:12:23
// 2 ^ 5 = 32 test.html:12:23
// 2 ^ 6 = 64 test.html:12:23
// 2 ^ 7 = 128 test.html:12:23
// 2 ^ 8 = 256 test.html:12:23
// 2 ^ 9 = 512 test.html:12:23
// 2 ^ 10 = 1024 test.html:12:23

// 1 ^ 2 = 2 test.html:18:3
// 2 ^ 2 = 4 test.html:18:3
// 4 ^ 2 = 16 test.html:18:3
// 16 ^ 2 = 256 test.html:18:3
// 256 ^ 2 = 65536 test.html:18:3
// 65536 ^ 2 = 4294967296 test.html:18:3
// 4294967296 ^ 2 = 18446744073709552000
// 18446744073709552000 ^ 2 = 3.402823669209385e+38
// 3.402823669209385e+38 ^ 2 = 1.157920892373162e+77
// 1.157920892373162e+77 ^ 2 = 1.3407807929942597e+154
// 1.3407807929942597e+154 ^ 2 = Infinity
</script>

Et

<script type="text/javascript"> "use strict";


function pow2x (a) {
return Math.pow(2,a);
}

function compound (f) {


return function (b) {
Itérateur–Générateur–Itérables -46/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
return function (c) {
return Math.pow(f(f(b)),2)
}
}
}

for(let k=0;k<=10;k++){
console.log(2,"^",k," = ", pow2x(k) )
}

console.log("")

var p=1;
for(let k=0;k<=10;k++){
var res=compound(pow2x)(k)(2)
console.log(p,"^",2,"^",2,"=", compound(pow2x)(k)(2) )
p=Math.sqrt(res)
}

// 2 ^ 0 = 1
// 2 ^ 1 = 2
// 2 ^ 2 = 4
// 2 ^ 3 = 8
// 2 ^ 4 = 16
// 2 ^ 5 = 32
// 2 ^ 6 = 64
// 2 ^ 7 = 128
// 2 ^ 8 = 256
// 2 ^ 9 = 512
// 2 ^ 10 = 1024

// 1 ^ 2 ^ 2 = 4
// 2 ^ 2 ^ 2 = 16
// 4 ^ 2 ^ 2 = 256
// 16 ^ 2 ^ 2 = 65536
// 256 ^ 2 ^ 2 = 4294967296
// 65536 ^ 2 ^ 2 = 18446744073709552000
// 4294967296 ^ 2 ^ 2 = 3.402823669209385e+38
// 18446744073709552000 ^ 2 ^ 2 = 1.157920892373162e+77
// 3.402823669209385e+38 ^ 2 ^ 2 = 1.3407807929942597e+154
// 1.157920892373162e+77 ^ 2 ^ 2 = Infinity

Itérateur–Générateur–Itérables -47/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// Infinity ^ 2 ^ 2 = Infinity
</script>

Itérateur–Générateur–Itérables -48/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

CHAPITRE 11 :

IT ÉRATIONS D' ÉNUM ÉRABLES :

Exemple d’itération :

On peut créer un objet itérable en le définissant de type


SET, dans une array, avec la commande

var itObj = new Set() ;

On crée alors son intance avec la commande

var itInst = iterable[Symbol.iterator]();

On parcourt les éléments de l’itérateur avec la méthode


.next(), comme dans l’illustration ci-dessous :

<script type="text/javascript"> "use strict";


const iterable = new
Set([0,1,2,4,8,16,32,64,128,256,512,1024]);

const it = iterable[Symbol.iterator]();
let tot="";

while (true) {
const res = it.next();

if (res.done) { break; }

const item = res.value;


tot += item + " = 2^" + Math.log2(item) + " | "
}
console.log(tot);
</script>

Itérateur–Générateur–Itérables -49/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
Exécution :

0 = 2^-Infinity | 1 = 2^0 | 2 = 2^ 1 |
4 = 2^2 | 8 = 2^ 3 | 16 = 2^ 4 | 32 = 2^ 5 |
64 = 2^ 6 | 128 = 2^ 7 | 256 = 2^ 8 | 512 = 2^ 9 |
1024 = 2^10 | 2048 = 2^11 | 4096 = 2^12 | 8192 = 2^13 |
16384 = 2^14 | 32768 = 2^15 | 65536 = 2^16 |

Exemple d’itération avec le caractère singulier ( ` ) =


ASCII 96 ou 60H ou <ALT-7> <ESPACE> en keybFr. utilisé
pour délimiter l'argument à la méthode.

Ce programme d’illustration est trop long, il sera découpé


et abondamment commenté dans les prochaines éditions.

<script type="text/javascript"> "use strict";


var obj = { obj:{} , L:"A" , 1:"Un", deux:2 ,
array:["texte",9,{o:"objet",s:6}]
};

// ACCÈS DIRECT AUX PROPRIÉTÉS


console.log(
obj['obj'] , obj[1] , obj['array'] , obj['array'][2]
)
// Object { } Un Array [ "texte", 9, {…} ]
// Object { o: "objet", s: 6 }

// ITÉRATIONS D'ÉNUMÉRABLES //

// `objet.${prop} <*> ${obj[prop]}`


//
console.log("---","***","---");

for (const prop in obj) {


console.log(`objet.${prop} <*> ${obj[prop]}`);
// Notez le caractère singulier ( ` )
// = ASCII 96 ou 60H ou <ALT-7><ESPACE> en keybFr.
// utilisé pour délimiter l'argument à la méthode

Itérateur–Générateur–Itérables -50/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// console.log()
// « objet. » est un littéral arbitraire
// ${prop} donne le nom (clé) de la propriété,
// ${obj[prop]} donne la valeur de la propriété.
}
// objet.1 <*> Un
// objet.obj <*> [object Object]
// objet.L <*> A
// objet.deux <*> 2
// objet.array <*> texte,9,[object Object]

// FOR (var prop IN obj)


// object
//
console.log("---","***","---");

for (var prop in obj) {


console.log(prop+" -> "+obj[prop]);
}
// 1 -> Un
// obj -> [object Object]
// L -> A
// deux -> 2
// array -> texte,9,[object Object]

// Object.entries(obj). FOREACH (([CLE,VAL])


// object
//
console.log("---","***","---");

Ob-
ject.entries(obj).forEach(([cle,val])=>console.log(cle+"
<-> "+val));
// 1 <-> Un
// obj <-> [object Object]
// L <-> A
// deux <-> 2
// array <-> texte,9,[object Object]

Itérateur–Générateur–Itérables -51/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// Object.entries(obj) . FOREACH(([CLE])
// object
//
console.log("---","***","---");

Object.entries(obj).forEach(([cle]) =>
console.log(cle));
// 1
// obj
// L
// deux
// array

// Object.entries(obj) . FOREACH(([VAL])
// object
//
console.log("---","***","---");

Object.entries(obj).forEach(([,val]) =>
console.log(val));
// Un
// Object { }
// A
// 2
// Array [ "texte", 9, {…} ]

// FOR(var [cle,val] OF Object.entries(obj))


// object
//
console.log("---","***","---");
for(var [cle,val] of Object.entries(obj))
console.log("*"+cle+' ^ '+val);
// *1 ^ Un
// *obj ^ [object Object]
// *L ^ A
// *deux ^ 2
// *array ^ texte,9,[object Object]

// Object.VALUES(obj)

Itérateur–Générateur–Itérables -52/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// object
//
console.log("---","***","---");
console.log(Object.values(obj));
// Array [ "Un", {}, "A", 2, […] ]

// FOR (var idx IN obj.array) {


// array
//
console.log("---","***","---");
for (var idx in obj.array) {
console.log(idx+" <-> "+obj.array[idx]);
}
// 0 <-> texte
// 1 <-> 9
// 2 <-> [object Object]

// FOR (var idx=0 ; idx<L ; idx++)


// array
//
console.log("---","***","---");
for (var idx=0,l=obj.array.length ; idx<l ; idx++) {
console.log(idx+" <<-> "+obj.array[idx]);
}
// 0 <<-> texte
// 1 <<-> 9
// 2 <<-> [object Object]

// Object.ENTRIES(obj.array) . FOREACH(([idx])
// array
//
console.log("---","***","---");
Object.entries(obj.array).forEach(([idx]) =>
console.log(idx+" -> "+obj.array[idx]));
// 0 -> texte
// 1 -> 9
// 2 -> [object Object]

Itérateur–Générateur–Itérables -53/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// FOR (var [idx] OF Object.entries(obj.array))
// array
//
console.log("---","***","---");
for(var [idx] of Object.entries(obj.array))
console.log("*"+idx+' ^ '+obj.array[idx]);
// *0 ^ texte
// *1 ^ 9
// *2 ^ [object Object]

// Object.values(obj.array)
// array
//
console.log("---","***","---");
console.log(Object.values(obj.array));
// Array [ "texte", 9, {…} ]

// FOR (var p IN obj.array[2])


// array
//
console.log("---","***","---");
for (var p in obj.array[2]) {
console.log(p+" -> "+obj.array[2][p]);
}
// o -> objet
// s -> 6
//
// Les indexes dans une Array sont juste des
// propriétés énumerables avec comme noms
// des entiers, et sont identiques aux
// propriétés d'un objet en général.

// FOR (var i IN s)
// String
//
console.log("---","***","---");
let s="Diasol";
for (var i in s) {
console.log(i+" -> "+s[i]);

Itérateur–Générateur–Itérables -54/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
}
// 0 -> D
// 1 -> i
// 2 -> a
// 3 -> s
// 4 -> o
// 5 -> l

// APPLICATIONS PRATIQUES

// HASOWNPROPERTY(prop)
//
console.log("---","***","---");
let triangle = {a: 1, b: 2, c: 3};
let epaisseur = {ep:"epais"};

function ColoredTriangle() {
this.color = 'red';
}

ColoredTriangle.aimepar = 15; // prop non héritable


ColoredTriangle.prototype = triangle; // héritable (prot)
ColoredTriangle.prototype = epaisseur; // héritable (prot)
ColoredTriangle.prototype.pds = 120; // héritable (prot)

var obj = new ColoredTriangle();


obj.brillant = true;

console.log("ColoredTriangle.aimepar =
"+ColoredTriangle.aimepar);
// ColoredTriangle.aimepar = 15

console.log("obj.aimepar = "+obj.aimepar);
// obj.aimepar = undefined

console.log("===> ownProperties de l'INSTANCE");


// ===> ownProperties de l'INSTANCE

console.log("---","***","---");
console.log(Object.getOwnPropertyNames(obj));
// Array [ "color", "brillant" ]

Itérateur–Générateur–Itérables -55/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI

for (const prop in obj) {


console.log("> ",prop+ " <*> "+obj[prop]);
// > color <*> red
// > brillant <*> true
// > ep <*> epais
// > pds <*> 120

if (obj.hasOwnProperty(prop)) {
console.log(`*** OWN PROP : obj.${prop} = $
{obj[prop]}`);
}
// *** OWN PROP : obj.color = red
// *** OWN PROP : obj.brillant = true
}

console.log("---","***","---");

console.log("===> ownProperties du CONSTRUCTEUR");


// ===> ownProperties du CONSTRUCTEUR

console.log(Object.getOwnPropertyNames(ColoredTriangle));
// Array [ "aimepar", "prototype", "length", "name" ]

for (const prop in ColoredTriangle) {


console.log("> ",prop+ " <*> "+ColoredTriangle[prop]);
// > aimepar <*> 15

console.log("---","***","---");
if (ColoredTriangle.hasOwnProperty(prop)) {
console.log(`*** OWN PROP : ColoredTriangle.${prop} =
${ColoredTriangle[prop]}`);
}
// *** OWN PROP : ColoredTriangle.aimepar = 15
}
</script>

Exécution :

4 -> o test.html:191:6
5 -> l test.html:191:6
--- *** --- test.html:205:3
Itérateur–Générateur–Itérables -56/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
ColoredTriangle.aimepar = 15 test.html:221:1
obj.aimepar = undefined test.html:224:1
===> ownProperties de l'INSTANCE test.html:227:1
--- *** --- test.html:230:3

Array [ "color", "brillant" ]


test.html:231:3
> color <*> red test.html:235:3
*** OWN PROP : obj.color = red test.html:242:5
> brillant <*> true test.html:235:3
*** OWN PROP : obj.brillant = true test.html:242:5
> ep <*> epais test.html:235:3
> pds <*> 120 test.html:235:3
--- *** --- test.html:248:1
===> ownProperties du CONSTRUCTEUR test.html:250:1

Array(4) [ "aimepar", "prototype", "length", "name" ]


test.html:253:1
> aimepar <*> 15 test.html:257:3
--- *** --- test.html:260:3
*** OWN PROP : ColoredTriangle.aimepar = 15 test.html:262:5

Kinshasa, le Sunday 14 April 2019 - 0:45:44 a4/p4

Mots-clés :

Variables statiques, Itération, énumérables, Set, function*,


générateur, itérateur, fonction génératrice, iterator, yield,
yield*, next, generator, constructibles, curry, currying,
closures, fermetures, curries, curryfication, boucle, test
conditionnel, javascript, opérateur new, ECMA, ECMASCRIPT,
arguments, paramètres.

Itérateur–Générateur–Itérables -57/60- dimanche, 17.


mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
DIASOLUKA Nz. Luyalu
Docteur en Médecine, Chirurgie & Accouchements (1977),
CNOM : 0866 - Spécialiste en ophtalmologie (1980)
Études humanités : Scientifique - Mathématiques & Physique.
Informaticien-amateur, Programmeur et WebMaster.

Chercheur indépendant, autonome et autofinancé, bénévole, sans


aucun conflit d’intérêt ou liens d'intérêts ou contrainte promotionnelle
avec qui qu’il soit ou quelqu’organisme ou institution / organisation
que ce soit, étatique, paraétatique ou privé, industriel ou commercial
en relation avec le sujet présenté.

+243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818

diasfb@mail2world.com

Autre Lecture :
https://www.scribd.com/document/374738470/Le-Plus-Grand-Secret-de-La-
Creation

D’autres publications pouvant aussi intéresser :

• https://www.scribd.com/document/377036251/Le-
Dosage-Des-Medicaments-en-Cac-Cas
• https://www.scribd.com/document/377035454/Le-
Hasard-Des-Thermometres-Non-contact-a-Infrarouge
• https://www.scribd.com/document/376222482/Petite-
Introduction-Aux-Fonctions-JavaScript
Itérateur–Générateur–Itérables -58/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
• https://www.scribd.com/document/376221919/La-Foi-
en-Jesus-Christ-Pour-Quoi-Faire
• https://www.scribd.com/document/375689778/Lacuite-
visuelle-angulaire
• https://www.scribd.com/document/375349851/La-
variable-This

https://www.scribd.com/document/375024162/Fonctions-
Imbriquees-en-JS
• https://www.scribd.com/document/374789297/Format-
Interne-Des-Objets-JavaScript

https://www.scribd.com/document/374788758/Iterations-
en-JavaScript
• https://www.scribd.com/document/374738470/Le-Plus-
Grand-Secret-de-La-Creation
• https://www.scribd.com/document/374597969/Nouvelle-
Formule-d-IMC-indice-de-doduite-Selon-Dr-Diasoluka
• https://www.scribd.com/document/373847209/Property-
Descriptors
• https://www.scribd.com/document/373833282/l-Objet-
Global-Window

https://www.scribd.com/document/372665249/Javascript-
Tome-II
• https://www.scribd.com/document/355291488/motilite-
oculaire-2
• https://www.scribd.com/document/355291239/motilite-
Itérateur–Générateur–Itérables -59/60- dimanche, 17.
mars 2019 (11:25 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
oculaire-I
• https://www.scribd.com/document/355290248/Script-d-
Analyses-Des-Reflexes-Pupillomoteurs

https://www.scribd.com/document/321168468/Renseigne
ments-Id-et-Anthropometriques

https://www.scribd.com/document/320856721/Emission-
31-Jul-2016

https://www.scribd.com/document/318182982/Complicati
on-Visuelle-du-Traitement-de-La-Malaria
• https://www.scribd.com/document/318180637/Rapport-
Entre-Oxymetrie-Et-Type-Respiration

https://www.scribd.com/document/315746265/Classificati
on-Des-Medicaments

https://www.scribd.com/document/315745909/Incongruen
ces-Heresies-et-Heterodoxies-de-la-Notion-de-
Laboratoire
• https://www.scribd.com/document/315745725/Rapport-
Entre-Oxymetrie-Et-Type-Respiration

Itérateur–Générateur–Itérables -60/60- dimanche, 17.


mars 2019 (11:25 )