javascript tome xiii - CLOSURES (CURRYING)
Transcription
javascript tome xiii - CLOSURES (CURRYING)
C L O S U R E S – C U R RY I N G ( fermetures – partial function application ) Po u r D é b u t a n t 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 11 : LES CLOSURES (CURRYING) EN JS : Définition d’une fonction Curry : « A CURRIED FUNCTION is one that requires multiple arguments but cannot accept all of them in a single call. » - Haskell B. Curry. Les fonctions en JS n’ont en principe aucune contrainte concernant le nombre de paramètres et d’arguments. On peut définir une fonction avec un nombre donné de paramètres formels, voire aucun paramètres, et l’appeler avec autant d’arguments qu’on veut, moins ou plus de (y compris avec zéro) arguments que de paramètres formels. Fonction sans paramètre et appelée avec des arguments : <script type="text/javascript"> "use strict"; let c=0; function f(){ // La même fonction sans paramètres console.log(++c+"* "); console.log(arguments); console.log(arguments[0]); console.log(arguments[1]); console.log(arguments[2]); console.log(arguments[3]); } f(); // Aucun paramètre f(["Un"]); // Un argument f(["Un"],{d:2}); // Deux arguments f(["Un"],{d:2},"Trois"); // Trois arguments f(["Un"],{d:2},"Trois",true); // 4 Arguments f(["Un"],{d:2},"Trois",true,5); // 5é=Argument de trop J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI </script> Exécution : 1* test.html:4:8 Arguments { … } test.html:5:8 undefined test.html:6:8 undefined test.html:7:8 undefined test.html:8:8 undefined test.html:9:8 2* test.html:4:8 Arguments { 0: […], … } test.html:5:8 Array [ "Un" ] test.html:6:8 undefined test.html:7:8 undefined test.html:8:8 undefined test.html:9:8 3* test.html:4:8 Arguments { 0: […], 1: {…}, … } test.html:5:8 Array [ "Un" ] test.html:6:8 Object { d: 2 } test.html:7:8 undefined test.html:8:8 undefined test.html:9:8 4* test.html:4:8 Arguments { 0: […], 1: {…}, 2: "Trois", … } test.html:5:8 Variables & Functions - 2 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI Array [ "Un" ] test.html:6:8 Object { d: 2 } test.html:7:8 Trois test.html:8:8 undefined test.html:9:8 5* test.html:4:8 Arguments { 0: […], 1: {…}, 2: "Trois", 3: true, … } test.html:5:8 Array [ "Un" ] test.html:6:8 Object { d: 2 } test.html:7:8 Trois test.html:8:8 true test.html:9:8 6* test.html:4:8 Arguments { 0: […], 1: {…}, 2: "Trois", 3: true, 4: 5, … } test.html:5:8 Array [ "Un" ] test.html:6:8 Object { d: 2 } test.html:7:8 Trois test.html:8:8 true test.html:9:8 Fonction avec des paramètres formels : <script type="text/javascript"> "use strict"; let c=0; function f(p1, p2){ // La même fonction sans paramaétres console.log(++c+"* "); console.log(p1); console.log(arguments[0]); console.log(p2); Variables & Functions - 3 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI console.log(arguments[1]); console.log(arguments[2]); console.log(arguments[3]); } f(); // Aucun paramètre f(["Un"]); // Un argument f(["Un"],{d:2}); // Deux arguments f(["Un"],{d:2},"Trois"); // Trois arguments f(["Un"],{d:2},"Trois",true); // 4 = Argument de trop f(["Un"],{d:2},"Trois",true,5); // 4 = Argument de trop </script> Exécution : 1* undefined undefined undefined undefined undefined undefined 2* Array [ "Un" ] Array [ "Un" ] undefined undefined undefined undefined 3* Array [ "Un" ] Array [ "Un" ] Object { d: 2 } Object { d: 2 } undefined undefined 4* Array [ "Un" ] Array [ "Un" ] Object { d: 2 } Object { d: 2 } Trois undefined 5* Variables & Functions test.html:4:8 test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 test.html:4:8 test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 test.html:4:8 test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 test.html:4:8 test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 test.html:4:8 - 4 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI Array [ "Un" ] Array [ "Un" ] Object { d: 2 } Object { d: 2 } Trois true 6* Array [ "Un" ] Array [ "Un" ] Object { d: 2 } Object { d: 2 } Trois true test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 test.html:4:8 test.html:5:8 test.html:6:8 test.html:7:8 test.html:8:8 test.html:9:8 test.html:10:8 Fonction Curry et Closure : Une fermeture de fonction se produit quand une fonction retourne une autre fonction. Tout l’environnement lexical de la première fonction (y compris toutes ses données locales) est conservée quand elle quitte. <script type="text/javascript"> "use strict"; function sr(){ var exp=11; return function(p){ console.log(exp*p) } } var f1=sr() f1(10) // Affiche 110 f1(5) // Affiche 55 </script> Un autre exemple : <script type="text/javascript"> function f() { var x=0 ; // pseudo static let f2 = function(y){ Variables & Functions "use strict"; - 5 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu x += y; return [y,x,p=>x*p]; } return f2; } JavaScript Tome-VI var fct=f(); for(var k=2;k<5;k++){ const r=fct(k * Math.round((Math.random()*10))); console.log("y==(k*Math)=="+r[0]+" | x=="+r[1]+ " | x+=y=="+(1*r[1]+r[0])+" | "+ "x("+r[1]+")*k("+k+")="+r[2](k)); } </script> // y==(k*Math)==18 | x==18 | x+=y==36 | x(18)*k(2)=36 // y==(k*Math)==9 | x==27 | x+=y==36 | x(27)*k(3)=81 // y==(k*Math)==24 | x==51 | x+=y==75 | x(51)*k(4)=204 Une fermeture (closure) se produit automatiquement à chaque fois que vous créez une fonction callback (callback function) ou retournez une fonction du sein d’une autre fonction. <script type="text/javascript"> "use strict"; function f1(p1){ var v1=p1*2; var f2=(p2)=>function f3(p3){return [v1,p1,p2,p3]} return f2; } var fct1=f1(5); var fct2=fct1(15); var r = fct2(20); console.log(r) // Array [ 10, 5, 15, 20 ] </script> ou encore : <script type="text/javascript"> function f1(p1){ var v1=p1/3; Variables & Functions "use strict"; - 6 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI var f2=(p2)=>function f3(p3){return [v1,p1,p2,p3]} return f2; // f1 retourne adresse de f2 et donc est curry } var i=new f1(30); // instanciation de i avec p1=30 console.log(i(15)(25)) // i appelle f2 avec p2=15, f2 appelle f3 avec p3=25 // En quittant, f1 a gardé son environnement lexical (p1 et v1). </script> // Array [ 10, 30, 15, 25 ] test.html:8:2 Une forme avancée de function Currying est la « partial function application ». Exemple classique simple de currying : <script type="text/javascript"> "use strict"; function add (x, y) {return x+y} let curry = (f, ...args) => f.bind.apply(f,[null, ...args]) let add4 = curry(add,4) console.log(add4(5)) //9 let add4n6 = curry(add4,6) console.log(add4n6()) //10 </script> Exécution : 9 10 test.html:7:3 test.html:10:3 Application de cet exemple à la puissance d’un nombre : <script type="text/javascript"> "use strict"; function fbase(x){ return function fpow(y){ return "Math.pow("+x+","+y+")="+ Variables & Functions - 7 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu Math.pow(x,y) ; } } JavaScript Tome-VI var fpow2=fbase(2); console.log("1 TB="+fpow2(40)+" Bytes") console.log("=Math.pow(1024,4)=" +Math.pow(1024,4)+" Bytes") </script> Exécution : 1 TB=Math.pow(2,40)=1099511627776 Bytes. =Math.pow(1024,4)1099511627776 Bytes test.html:11:1 test.html:12:1 Fonctionnement de l’exemple classique de currying ci-dessus : <script type="text/javascript"> "use strict"; function add (x, y ,z) {return x+y+z} // Définition de la foncition « add » qui // travaillera cette fois-ci avec 3 parmétres vs 2. // Avec sa commande return, la fonction add conserve // son environnement lexical aprés son exit, // notamment les premiers paramètres lui envoyés // (ainsi que leurs exacts noms) lors de l'appel // avec p.e. l'instruction : // add4 = curry(add,4) let curry = (f, ...args) => f.bind.apply(f,[null, ...args]) // La fonction fléchée nommée ici « curry » // lie le paramètre « f » à l'argument de son appel qui est // la fonction « add » ci-dessus, tel que spécifié par // le premier paramètre de « curry » (dans l'instruction // ci-dessous « add4 = curry(add,4), » et qui est aussi // l'argument de la fonction « apply » qui lie la fonction // add ci-dessus avec l'array des arguments ici // [null et ...args], ...args représentant la liste des // arguments d'appel de curry. Variables & Functions - 8 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI // curry est donc un pointeur sur la fonction add. // Chaque fois donc qu'on appellera curry c'est add qui // s'exécutera. // // Aprés la double fléche donc, la // définition / description de la fonction flechée // qui s'exécute sur le champ et retourne // (dans « curry ») la fonction qui est associée au // paramètre « f » dans les appels à « curry » // (donc add) en la faisant intervenir comme // premier paramètre de l'appel à « curry », // mais aussi les autres arguments qui viennent aprés // ce 1er param. // Par exemple, dans l'appel « add4 = curry(add,4) // ci-dessous la variable « add4 » reçoit la valeur // renvoyée par fonction anonyme fléchée « curry » qui est // [l'adresse de ] la fonction add ci-haut. // // L'appel de add avec curry configure un environnement // lexical durable de add. // L'appel direct de add (le deuxiéme) lui envoie un surplus // de paramètres, mais seulement le nombre de paramètres prévus // dans la définition de la fonction add est nécessaire, // le surplus n'a aucun effet. // Un troisiéme appel sembe ne pas vouloir marcher. let add4 = curry(add,4) // Définition de la variable add4 qui reçoit la valeur // retournée par l'appel de la fonction « curry », celleci // (curry) transmet la valeur 4 à la fonction add // qui on le sait conservera à son exit la valeur 4 dans son // environnement lexical. elle-même // appelle la fonction add avec une liste de sauf le dernier. // Appe de add via add4 avec comme argument 4. // // // // console.log(add4(5,6)) Appel de « add » via add4 avec deux derniers arguments Comme tous les paramètres formels ont maintenant chacun sa correspondance, la fonction add s'exécute avec les trois paramètres et calcule l'expression [dont le Variables & Functions - 9 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI // résultat est retourné explicitement]. // // // // // // // // // // // Pour preuve, on appelle d'abord add avec 2 arguments, avec add4 = curry(add,4,5) puis on doit l'appeler avec un troisiéme argument. avec console.log(add4(6)) add4 = curry(add,4,5) Ci-desus, Redéfinition de notre fonction add4, cette fois-ci elle appelle add avec 2 premiers paramètres, le 4 et le 5 dès le premier tour . console.log(add4(6)) Appel de add via add4 avec le dernier paramètre. Tous les paramètres de add étant servis, la fonction s'exécute. // Autre preuve, on appelle add directement avec 3 arguments, // avec add4 = curry(add,6,7,8) // et on ne l'appele plus avec un argument supplémentaire. let add4n6 = curry(add,6,7,8) console.log(add4n6()) // Redéfinition de add4 ci-dessus, avec // 1er appel sans aucun paramètre add4 = curry(add) // 2é appel de add4 avec tous les trois paramètres console.log(add4(9,10,11)) console.log(add4(10,20,30)) </script> Exécution : 15 15 21 30 60 test.html:57:3 test.html:73:8 test.html:82:3 test.html:88:3 test.html:89:3 Code similaire, enrichi et avec les directives « const » « let » et « var » et la fonction fléchée (expression de fonction) : Variables & Functions - 10 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI <script type="text/javascript"> "use strict"; // fpow est une fonctio ordinaire // qu'on utilisera dans le currying. function fpow (x, y) { return "Math.pow("+x+","+y+") = "+ Math.pow(x,y) } // Jamais de retour à la ligne avant le => const curry = (f, ...args) => f.bind.apply(f,[null, ...args]) ////////////////////////////// ///// CONFIGURONS 2 ENVIRONNEMENTS LEXICAUX ////////////////////////////// // Définition de la variable pow5 à pointer // la fonction curry let pow5 = curry(fpow,5) // Configure 2é environt lexical pow10 avec x=10 var pow10 = curry(fpow,10) ////////////////////////////// // EXECUTION EFFECTIVE DE LA FONCTION ////////////////////////////// //A/////////////////////////// ///// Appel DIRECT fpow via l'instruction // powx=curry( *** F_POW *** sans args) // Excusez le underscore et les majuscules. // Appel fpow avec dernier arg y=1 => exec fct // ... AVEC UN PARAMETRE. console.log(pow5(1)) // Appel fpow avec dernier arg y=1 => exec fct console.log(pow10(1)) Variables & Functions - 11 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI //B////////////////////////// ///// Appel INDIRECT de fpow via alias curry // powx = curry(*** POW_X *** , 2éarg) // sans _f_ Excusez les majuscules. // x garde tjs sa valeur x=5 ds pow5 // Appel de fpow avec un autre 2é arg via pow5 let pow1 = curry(pow5,6) // 2e appel de fpow sans arg // ... SANS UN PARAMETRE. console.log(pow1()) // x garde tjs sa valeur x=10 ds pow10 // Appel de fpow avec un autre 2é arg via pow10 let pow2 = curry(pow10,6) // 2e appel de fpow sans arg console.log(pow2()) // x garde tjs sa valeur x=5 ds pow5 // Appel de fpow avec un autre 2é arg via pow5 let pow3 = curry(pow5,3) // 2e appel de fpow sans arg console.log(pow3()) // x garde tjs sa valeur x=10 ds pow10 // Appel de fpow avec un autre 2é arg via pow5 let pow4 = curry(pow10,3) // 2e appel de fpow sans arg console.log(pow4()) //A/////////////////////////// ///// Encore Appel DIRECT fpow via curry // x garde tjs sa valeur x=5 ds pow5 // Appel fpow avec dernier arg y=5 => exec fct console.log(pow5(10)) </script> Exécution : Variables & Functions - 12 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu Math.pow(5,1) = 5 Math.pow(10,1) = 10 Math.pow(5,6) = 15625 Math.pow(10,6) = 1000000 Math.pow(5,3) = 125 Math.pow(10,3) = 1000 Math.pow(5,10) = 9765625 JavaScript Tome-VI test.html:36:2 test.html:39:2 test.html:52:2 test.html:58:2 test.html:64:2 test.html:70:2 test.html:77:2 Exemple un peu plus complexe : <script type="text/javascript"> "use strict"; function congrat (cat, age, id) { // if a sage, use Senhor, else use Merde var phrases = cat === "sage" ? "Senhor " : "Merde "; var phrase = cat === "sage" ? "Mes Respects " : "Et toi là-bas, "; if (age >= 45) { return phrase + phrases + id + "."+dummy; } else { return "Bonjour, " + id + "."; } } var congratAdSag = congrat.bind (null,"sage",50); // On lie la variable congratAdSag avec la fonction congrat, et // on appelle congrat avec l'argument this=null, et les autres // sauf le dernier (cat = "sage" et age = 45). // congrat exécute et comme age>25, elle RETOURNE dans le vide // quelque chose : "Mes respects, Senhor.." Variables & Functions - 13 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI // Ce return préserve l'environnement syntactical de congrat. // // Quand ci-dessous on appelle de nouveau la fonction congrat // par son alias et avec le dernier paramètre (non exploité), // l'ID de la personne, age est toujours > 25, et cat = "mâle". // Elle réexécute donc l'instruction de la ligne 2 et // retourne dans la variable ret la chaîne et les paramètres // que l'on peut afficher avec l'instruction console.log. ret = congratAdSag("Vladimir PUTIN"); console.log(ret); // Le même mécanisme que ci-dessus. var congrJeunes = congrat.bind (null, "", 40); ret = congrJeunes ("vedette en herbe"); console.log(ret); ret = congrJeunes ("Les éléves"); console.log(ret); var ret = congratAdSag ("Mohamar Kaddafi"); console.log(ret); var congratAdBuru = congrat.bind (null, "bourique", 55); ret = congratAdBuru ("Leotar Kathy"); console.log(ret); // Voici en clair comment fonctionne congrat. console.log(congrat.bind (null, "bougre", 60)); // Pointeur sur fonction console.log(congrat.bind (null, "bougre", 60)()); // Exécution de la fonction. Variables & Functions - 14 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu </script> JavaScript Tome-VI Exécution avec FIREFOX : Mes Respects Senhor Vladimir PUTIN. Bonjour, vedette en herbe. Bonjour, Les éléves. Mes Respects Senhor Mohamar Kaddafi. Et toi là-bas, Merde Leotar Kathy. function bound congrat() bound congrat() name: "bound congrat" __proto__: function () Et toi là-bas, Merde undefined. Exécution avec YANDEX : Mes Respects Senhor Vladimir PUTIN. Bonjour, vedette en herbe. Bonjour, Les éléves. Mes Respects Senhor Mohamar Kaddafi. Et toi là-bas, Merde Leotar Kathy. ƒ congrat(cat, age, id) { // if a sage, use Senhor, else use Merde var phrases = cat === "sage" ? "Senhor " : "Merde "; var phrase = cat === "sage" ? "Mes Respects " : "Et toi là-bas, ";… Et toi là-bas, Merde undefined. Fonction fléchée à multiple imbrication (ici trois niveau) : <script type="text/javascript"> Variables & Functions - 15 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI "use strict"; var x = (a) => (b) => (c) => (d) => a + b + c + d; console.log( x(1)(2)(3)(4) ); </script> Exécution : 10 Ce code simple est l’exact équivalent de celui-ci plus « cumbersome » (c’est plus imagé que de dire « encombrant »), et par ironie, c’est pour afficher seulement un « 10 ». : <script type="text/javascript"> "use strict"; var fa, fb, fc, fd; // Noms des fonctions fa=function(a){ return fb=function(b){ return fc=function(c){ return fd=function(d){ return a+b+c+d } } } } var res = fa(1)(2)(3)(4); console.log(res); </script> Exécution : 10 Ce code peut s’écrire dans les détails comme suit : <script type="text/javascript"> "use strict"; var a, b, c; // Noms des fonctions Variables & Functions - 16 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI // Attention : j'ai utilisé les mêmes noms // pour leurs paramètres : Pas de // confusion possible à cause d'un NameSpace // différent pour chaque catégorie de données : // Les variables ont leur NameSpace, // Les fonctions ont le leur (si "use stric"), // Les.paramètres ont le leur... a=function(a){ return b=function(b){ return c=function(c){ return function(d){ return a+b+c+d } } } } // // // // // L'argument de la fonction a() sera conservé à sa sortie dans son environnement lexical. Cet environnement lexical restera accessible aux fonctions imbriquées dans elle. Ainsi en est-il pour les fonctions imbriquées. var b(). tmp tmp var params tmp = a(1); // a() passe à tmp l'adresse de = b(2); // b() passe à tmp l'adresse de c(). = c(3); // c() passe à tmp l'adresse de d(). res = tmp(4) // d() s'exécute avec tous les console.log(res); </script> Exécution : 10 On peut aussi moins efficacement l’écrire comme ceci : Variables & Functions - 17 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI <script type="text/javascript"> "use strict"; var fa, fb, fc, fd; // Noms des fonctions fa=function(){ const a=aL; return fb=function(){ let b=bL; return fc=function(){ var c=cL; return fd=function(){ let d=dL; return a+b+c+d } } } } const aL=1, bL=2, cL=3, dL=4; let res = (fa)(fb)(fc)(fd)(); console.log(res); </script> Exécution : 10 CHAPITRE 12 : LES FONCTIONS CALLBACK : Exécutent pour chaque élément d’une collection itérable (Arrays...) <script type="text/javascript"> 'use strict'; // Definir la fonction callback. function primes(val /*, idx, ar */) { let high = Math.round(Math.sqrt(val)) Variables & Functions - 18 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI for (var div = 2; div <= high; div++) { if (val % div == 0) return false; } return true; } // Créez l'array original var nombres = []; for(var k=101;k<=150;k+=2) nombres.push(k); // Extraire les nombres premiers (prime numbers). var primes = nombres.filter(primes); console.log(primes); </script> Exécution : Array [ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149 ] <script type="text/javascript"> 'use strict'; // Créez l'Array initiale. var arr = ["texte1", [], "texte2", {}, "texte3"]; // Filtrez var res = arr.filter( function (dummy) { return (typeof dummy === 'string'); } ); console.log(res); </script> Exécution : Array [ "texte1", "texte2", "texte3" ] […] Variables & Functions - 19 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu 0: "texte1" 1: "texte2" 2: "texte3" length: 3 __proto__: Array [] JavaScript Tome-VI Avec « Object.getOwnPropertyNames (window) » : <script type="text/javascript"> 'use strict'; var noms_css = Object.getOwnPropertyNames(window).filter(fcss); for (var i in noms_css) console.log(noms_css[i]); // Extraire les noms commençant par "css". function fcss(val) { if ((val.substr(0, 3)).toLowerCase() == "css") return true; else return false; } </script> Exécution : CSSStyleRule CSSFontFaceRule CSSPrimitiveValue CSSStyleDeclaration CSSStyleSheet CSSPageRule CSSSupportsRule CSSMozDocumentRule CSSKeyframeRule CSSGroupingRule CSS2Properties CSSFontFeatureValuesRule Variables & Functions - 20 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu CSSRuleList CSSMediaRule CSSCounterStyleRule CSSImportRule CSSValue CSSNamespaceRule CSSRule CSS CSSKeyframesRule CSSConditionRule CSSValueList JavaScript Tome-VI Avec Array.map() : <script> var myArray = [1, 2, 3]; var newArray = myArray.map(function(x) { return x+". " + x*x; }); console.log(newArray); </script> Exécution : (3) ["1. 1", "2. 4", "3. 9"] 0: "1. 1" 1: "2. 4" 2: "3. 9" length: 3 __proto__: Array(0) Array.map() : <script> "use strict"; var txt = [ "Kelakonov", ["Kretchnonskof","Qelaïnokonovitchsk"], {nom:"Andreanopovickz",pnom:"Bretilonov"}, Variables & Functions - 21 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu "Kenailovocz", "Qelaïnkenikov" ]; JavaScript Tome-VI // Accés par callback automatique let res=txt.map( dm => dm ); console.log(res); // Accés par callback automatique res=txt.map( dm => dm.length ); console.log(res); // Accés par callback automatique res=txt.map( dm => typeof dm ); console.log(res); // Accés conventionnels (individuels) console.log(txt[1][0]+" "+txt[1][1]); console.log(txt[2].nom+" "+txt[2].pnom); console.log(txt[2]); // Accés par callback automatique console.log(txt[1].map(x=>x)); ////// TypeError: txt[2].map is not a function ////// test.html:30:13 // console.log(txt[2].map(x=>x)); </script> Exécution : Array [ "Kelakonov", […], {…}, "Kenailovocz", "Qelaïnkenikov" ] Array [ 9, 2, undefined, 11, 13 ] Array [ "string", "object", "object", "string", "string" ] Kretchnonskof Qelaïnokonovitchsk Andreanopovickz Bretilonov Object { nom: "Andreanopovickz", pnom: "Bretilonov" } Array [ "Kretchnonskof", Variables & Functions - 22 / 28 - test.html:13:1 test.html:17:1 test.html:21:1 test.html:24:1 test.html:25:1 test.html:26:1 jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu "Qelaïnokonovitchsk" ] JavaScript Tome-VI test.html:29:1 Plusieurs façons d’utiliser Array.map() : <script type="text/javascript"> "use strict"; var r; var mot = [ 'Anticonstitutionnellement', 'doc', 'sarcophage', '', 'Q' ]; r=mot.map(function(el) { return el.length; }); // Array [ 25, 3, 10, 0, 1 ] console.log(r); r=mot.map(({length}) => length); // Array [ 25, 3, 10, 0, 1 ] console.log(r); r=mot.map((el) => el.length); // Array [ 25, 3, 10, 0, 1 ] console.log(r); r=mot.map((el) => { return el.length; }); // Array [ 25, 3, 10, 0, 1 ] console.log(r); </script> Avec Array.filter() : <script> "use strict"; var dslimites = function(val) { if (typeof val !== 'number') return false; else Variables & Functions - 23 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI return val >= this.minimum && val <= this.maximum; } var numbers = [25, 17, "15", 6, "texte", -1, 12]; var oLimites = { minimum: 10, maximum: 20 } var result = numbers.filter(dslimites, oLimites); console.log(result); </script> Exécution : Array [ 17, 12 ] 0: 17 1: 12 length: 2 __proto__: Array [] CHAPITRE 13 : AFFICHER LE tagName D’UN ÉLÉMENT : <script type="text/javascript"> function ftag(e) { var targ if (!e) var e = window.event if (e.target) targ = e.target else if (e.srcElement) targ = e.srcElement if (targ.nodeType == 3) // Contourner bug ds Safari targ = targ.parentNode var tnam tnam=targ.tagName console.log("Element clické = <" + tnam + ">.") } Variables & Functions - 24 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu </script> JavaScript Tome-VI <body onmousedown="ftag(event)"> Clickez cette page n'importe où.<br> <h1>Header H1</h1> <span>Span SPAN</span> <img width="30" height="25"> <dummy>Fausse balise DUMMY</dummy> <select>Liste de sélection SELECT <option>Option 0 <option>Option 1 <option>Option 2 </select> </body> Exécution : Clickez cette page n'importe où. Header H1 Span SPAN Element Element Element Element Element Element Element Fausse balise DUMMY clické clické clické clické clické clické clické = = = = = = = <H1>. <BODY>. <SPAN>. <IMG>. <DUMMY>. <SELECT>. <OPTION>. CHAPITRE 14 : POBLÈME AVEC DOCUMENT.WRITE : Ici le programme exécute sans problème : <script type="text/javascript"> function f(){ v=document.getElementById("idiv").innerHTML; Variables & Functions - 25 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu v=v.toUpperCase(); console.log(v); } </script> JavaScript Tome-VI <body onload=f() id="ibody"> <div id="idiv"">texte initial</div> </body> Exécution : texte initial T E X T E I N I T I A L Dès qu’on place un «document.write» devant les «getElementByID», ceux-ci ne sont plus reconnus. C’est ce que Firefox signale avec le message ci-dessus : Un arbre non équilibré a été écrit en utilisant « document.write() » provoquant une nouvelle analyse de données provenant du réseau. Pour plus d’informations, consultez https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing <script type="text/javascript"> function f(){ document.write("Alléluia") v=document.getElementById("idiv").innerHTML; v=v.toUpperCase(); console.log(v); } </script> <body onload=f() id="ibody"> <div id="idiv"">texte initial</div> </body> Exécution : TypeError: document.getElementById(...) is null Variables & Functions - 26 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu docwrite.html:4:8 JavaScript Tome-VI Une des solutions c’est, au lieu d’écrite avec le «document.write» par un append un append avec par exemple avec un « document.getElementById("ibody").innerHTML+= » <script type="text/javascript"> "use strict"; function f(){ // document.write("Alléluia"); document.getElementById("ibody").innerHTML+= "Alleluia"; var v; v = document.getElementById("idiv").innerHTML console.log(v); v = v.toUpperCase(); console.log(v); } </script> <body onload=f() id="ibody"> <div id="idiv""> texte initial </div> </body> Exécution : Dans le document : texte initial Alleluia Dans la console : texte initial Variables & Functions test.html:8:6 - 27 / 28 - jeudi, 4. avril 2019 (10:46 ) J.D.B. DIASOLUKA Nz. Luyalu TEXTE INITIAL Variables & Functions JavaScript Tome-VI test.html:10:6 - 28 / 28 - jeudi, 4. avril 2019 (10:46 )