javascript tome vi - fonctions imbriquees en JS

Transcription

javascript tome vi - fonctions imbriquees en JS
fonctions imbriquées en javascript
(nested function)
J AVA S C R I P T (Programmation Internet) V O L . V I
J.B. Dadet DIASOLUKA Luyalu Nzoyifuanga
+243 - 851278216 - 899508675 - 995624714 - 902263541 - 813572818
La dernière révision de ce texte est disponible sur CD.
CHAPITRE 12 : L e s f o n c t i o n s i m b r i q u é e s e n j a v a s c r i p t
Contrairement aux langages C, en JavaScript les fonctions peuvent être imbriquées . Ceci parce qu’en JavaScript les fonctions
sont des « objets de premier ordre » on dit aussi « objets de pre-
mière classe » car elles peuvent être manipulées, échangées,
avoir des propriétés et des méthodes, et surtout être passées en
paramètre, comme tout autre objet JS. Une fonction JS, ordinaire
soit-elle (càd sans propriétés ni méthodes propres), reste donc ni
plus ni moins un objet Function (callable object), et inversement
(tout objet est une fonction). Or justement les méthodes aussi
sont ni plus ni moins des fonctions.
Outre ses méthodes, une fonction peut posséder des fonctions
ordinaires imbriquées [tout comme elle peut avoir des variables
locales propres]. Mais une fonction imbriquée ne peut être appelée directement que du sein de la fonction qui l’englobe, jamais du
dehors de cette fonction englobante. Ceci s’applique aussi aux
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
variables locales propres à la fonction.
Donc fonctions imbriquées et variables propres d’une fonction ne
sont pas directement accessible du dehors de la fonction englo-
bante, sauf si on les retourne implicitement avec un « return ».
Mais rappelez-vous que « return ») ne peut retourner qu’une et
une seule valeur, et que pour retourner plusieurs valeurs [à une
unique occasion] il faut les placer dans une structure telle que
Array ou Objetde retour.
<script type="text/javascript"> "use strict";
let fext = p => {
let m=2;
return _ => [m, Math.pow(m , p)];
}
let exp = Math.round(Math.random()*10);
let rtvf = fext(exp);
//
//
//
//
Initialise à la valeur de la variable « exp »
le paramètre p de la fonction englobante fext();
et récupération de l'adresse de la
fonction retournée par englobante fext().
let retval = rtvf();
//
//
//
//
//
//
Appel de la fonction « ANONYME » retournée
par la fonction englobante.
Cette fonction imbriquée continuera à accéder
aux paramètres et variables locales de la
fonction qui l'englobe.
La valeur (une ARRAY) retournée par la
Fonctions Imbriquées
- 2 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// fonction anonyme imbriquée est récupérée
// par la variable « retval ».
console.log(
retval[0] + "^" + exp + " = " + retval[1]
);
</script>
Exécution:
2^10 = 1024
test.html:28:2
Les éléments renvoyés directement comme tels (pas leur pointeur) avec un « return » ne peuvent naturellement pas être modifiés dans leur milieu d’origine (l’intérieur de la fonction englobante) à partir de l’extérieur de la fonction englobante sauf si c’est
un pointeur sur eux qui a été renvoyé (mais en JavaScript il
n’existe pas de pointeur sur variable ordinaire).
<script type="text/javascript"> "use strict";
let fext = p => {
let m=2;
return _ => [m, Math.pow(m , p)];
}
let exp = Math.round(Math.random()*10);
let rtvf = fext(exp);
//
//
//
//
Initialise à la valeur de la variable « exp »
le paramètre p de la fonction englobante fext();
et récupération de l'adresse de la
fonction retournée par englobante fext().
Fonctions Imbriquées
- 3 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
let retval = rtvf();
//
//
//
//
//
//
//
//
Appel de la fonction « ANONYME » retournée
par la fonction englobante.
Cette fonction imbriquée continuera à accéder
aux paramètres et variables locales de la
fonction qui l'englobe.
La valeur (une ARRAY) retournée par la
fonction anonyme imbriquée est récupérée
par la variable « retval ».
console.log(
retval[0] + "^" + exp + " = " + retval[1]
);
// Affichage de la valeur multiple retournée
// par la fonction imbriquée.
///////////////////////////////////////////////
// Tentative de Modification d'une fonction //
// imbriquée en dehors de la fonction
//
// qui l'englobe.
//
///////////////////////////////////////////////
let fprot = _ => console.log("Success");
// Définition d'une nouvelle fonction (fléchée)
retval.prototype = fprot;
// On colle, de l'extérieur, un prototype à
// la fonction imbriquée.
retval.prototype();
Fonctions Imbriquées
- 4 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// On appelle ce prototype bien sûr
// toujours de l'extérieur.
console.dir(rtvf);
// Vérification de la configuration actuelle
// de notre fonction imbriquée, via son
// pointeur « rtvf ».
// function fext()
// fext()
//
length: 1
//
name: ""
//
<prototype>: function ()
test.html:66:3
// Nous voyons bien ci-dessus que notre
// pointeur « rtvf » représente bien (pointe sur)
// notre fonction englobante externe « fext() ».
console.dir(retval);
// Vérification de la configuration actuelle
// de notre fonction imbriquée, via son
// pointeur « retval ».
// Array [ 2, 16 ]
test.html:86:3
// (2) […]
//
0: 2
//
1: 16
//
length: 2
//
prototype: function fprot()
//
<prototype>: Array []
//
//
//
//
//
Nous voyons bien que la valeur retournée par
la fonction imbriquée et une ARRAY,
donc une valeur multiple,
et que le prototype de cette fonction
a bel et bien été "sémaphoré" sur « frot() ».
Fonctions Imbriquées
- 5 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
</script>
Rappelez-vous aussi que toute instruction qui vient après « return » dans un même bloc d’instruction est ignoré pour la simple
et bonne raison que l’exécution ne se poursuit pas au-delà de
return, à moins d’y aller grâce aux labels et une instruction « goto » en amont de « return ». Mais le « goto » est trop intrusif et
comporte beaucoup d’autres inconvénients :
http://www.acm.org/classics/oct95/
Bien entendu, il reste tout de même des situations où « goto »
rest préférable, plus rapide et plus performant, mais il n’existe
dans JavaScript que comme mot-clé mais n’y est pas utilisable.
Le « label » en JavaScript n’étiquette pas n’importe quel endroit
du code source, mais étiquette seulement [le début d’] une boucle
qu’on peut quitter avec une « break » ou reboucler avec une
« continue » qui se substituent à « goto ».
Les deux versions d’un même code ci-dessous relatif à des
boucles imbriquées (l’une sans l’instructio « goto » et l’autre avec
l’instruction « goto » à laquelle on a substitué l’istruction
« break ») font presque la même chose, mais dommage que ça
Fonctions Imbriquées
- 6 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
montre une certaine supériorité de « goto » dans certaines circonstances.
<script type="text/javascript"> "use strict";
let tmp=null, cpt=null, faux=null;
</script>
<script type="text/javascript"> "use strict";
console.log("SANS « GOTO LABEL »");
const m1 = [7,3,15,20,1,5,9,15,6,35,27];
const e1 = [1,25,3,5,7,9,15,75];
console.log(m1,e1)
console.log("")
faux=cpt=0;
tmp=""
const d1=new Date();
for(let km=0,kml=m1.length ; km<kml ; km++){
for(let ke=0,kel=e1.length ; ke<kel ; ke++){
tmp+= ++cpt +" ";
if(!(m1.includes(e1[ke]))) {
//
faux++; m1.push(e1[ke]); break;
// ou
faux++; m1.push(e1[ke]);ke=kel;
}
}
//
if(faux) break;
// ou
if(faux) km=kml;
}
if(faux) console.log(m1," .not.included ",e1)
else console.log(m1," included ",e1)
console.log("Durée = ",((new Date())-d1)/1000+" secs")
console.log(tmp+" passes.")
</script>
<script type="text/javascript"> "use strict";
console.log("");
Fonctions Imbriquées
- 7 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
</script>
JavaScript Tome-VI
<script type="text/javascript"> "use strict";
console.log("AVEC « GOTO LABEL »");
const m2 = [7,3,15,20,1,5,9,15,6,35,27];
const e2 = [1,25,3,5,7,9,15,75];
console.log(m2,e2)
console.log("")
faux=cpt=0;
tmp=""
const d2=new Date();
quitLab:
for(let km=0,kml=m2.length ; km<kml ; km++){
forthLab:
for(let ke=0,kel=e2.length ; ke<kel ; ke++){
tmp+= ++cpt +" ";
if(!(m2.includes(e2[ke]))) {
faux++; m2.push(e2[ke]);
break quitLab;
// Quitter la boucle qui suit quitLab.
}
else continue forthLab;
}
}
if(faux) console.log(m2," .not.included ",e2)
else console.log(m2," included ",e2)
console.log("Durée = ",((new Date())-d2)/1000+" secs")
console.log(tmp+" passes.")
</script>
Exécution :
1. Les deux versions sans « goto » et avec « goto » s’arrêtent
dès qu’elles rencontrent le premier élément de l’array « e »
Fonctions Imbriquées
- 8 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
(d’échantillons) qui n’existe pas dans l’array « m » (modèle ou
de référence) et qu’elles ajoutent cet élément de trop à l’array
modèle, et s’arrêtent là.
2. La version sans « goto » a exécuté en 0.001 secs, alors que
celle avec « goto » a exécuté en moins de temps (0.000 sec).
3. Les deux versions (sans et avec « goto ») ont exécuté avec le
même nombre de passes = 2.
07:25:23,833 SANS « GOTO LABEL »
test.html:7:3
07:25:23,837
Array(11) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27 ]
Array(8) [ 1, 25, 3, 5, 7, 9, 15, 75 ]
test.html:10:3
07:25:23,843
Array(12) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27, 25 ]
.not.included
Array(8) [ 1, 25, 3, 5, 7, 9, 15, 75 ]
test.html:29:12
07:25:23,845 Durée = 0.003 secs
07:25:23,845 1 2 passes.
test.html:31:3
test.html:32:3
07:25:23,847 AVEC « GOTO LABEL » test.html:46:3
07:25:23,848
Array(11) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27 ]
Array(8) [ 1, 25, 3, 5, 7, 9, 15, 75 ]
test.html:49:3
07:25:23,849
Fonctions Imbriquées
- 9 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
Array(12) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27, 25 ]
.not.included
Array(8) [ 1, 25, 3, 5, 7, 9, 15, 75 ]
test.html:70:12
07:25:23,851 Durée = 0.001 secs
test.html:72:3
07:25:23,851 1 2 passes.
test.html:73:3
Ci-après, une versions qui parcourt tous les éléments de l’array
« e » des échantillons pour les comparer tous aux éléments de
l’array modèle « m », et ajoute à cette dernière tous les éléments
qui sont de trop dans l’array d’échantillons.
<script type="text/javascript"> "use strict";
let tmp=null, cpt=null, faux=null;
</script>
<script type="text/javascript"> "use strict";
console.log("SANS « GOTO LABEL »");
const m1 = [7,3,15,20,1,5,9,15,6,35,27];
const e1 = [1,25,3,85,7,9,15,75];
console.log(m1,e1)
console.log("")
faux=cpt=0;
tmp=""
const d1=new Date();
for(let km=0,kml=m1.length ; km<kml ; km++){
for(let ke=0,kel=e1.length ; ke<kel ; ke++){
tmp+= ++cpt +" ";
if(!(m1.includes(e1[ke]))) {
//
faux++; m1.push(e1[ke]); break;
// ou
faux++; m1.push(e1[ke]); ///////////// ke=kel;
}
Fonctions Imbriquées
- 10 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
}
//
if(faux) break;
// ou
//////////////////
if(faux) km=kml;
}
if(faux) console.log(m1," .not.included ",e1)
else console.log(m1," included ",e1)
console.log("Durée = ",((new Date())-d1)/1000+" secs")
console.log(tmp+" passes.")
</script>
<script type="text/javascript"> "use strict";
console.log("");
</script>
<script type="text/javascript"> "use strict";
console.log("AVEC « GOTO LABEL »");
const m2 = [7,3,15,20,1,5,9,15,6,35,27];
const e2 = [1,25,3,85,7,9,15,75];
console.log(m2,e2)
console.log("")
faux=cpt=0;
tmp=""
const d2=new Date();
quitLab:
for(let km=0,kml=m2.length ; km<kml ; km++){
for(let ke=0,kel=e2.length ; ke<kel ; ke++){
tmp+= ++cpt +" ";
if(!(m2.includes(e2[ke]))) {
faux++; m2.push(e2[ke]);
// break quitLab; // On ne quitte pas la boucle externe.
}
else continue;
}
}
if(faux) console.log(m2," .not.included ",e2)
else console.log(m2," included ",e2)
Fonctions Imbriquées
- 11 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log("Durée = ",((new Date())-d2)/1000+" secs")
console.log(tmp+" passes.")
</script>
Exécution :
1. Les deux versions sans « goto » et avec « goto » ne s’arrêtent
que quand ils ont fini de parcourir tous les éléments de l’array
« e » (d’échantillons) en les comparant avec les éléments de
l’array « m » (modèle ou de référence) et lui ajoutent tous les
éléments qui sont de trop dans l’array « e ».
2. La version sans « goto » a exécuté en 0.003 secs, alors que
celle avec « goto » a exécuté en moins de temps (0.002 sec).
3. Les deux versions (sans et avec « goto ») ont exécuté avec le
même nombre de passes = 88.
test.html:7
SANS « GOTO LABEL »
test.html:10
(11) [7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27]
(8) [1, 25, 3, 85, 7, 9, 15, 75]
test.html:29
(14) [7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27, 25, 85, 75]
" .not.included "
(8) [1, 25, 3, 85, 7, 9, 15, 75]
test.html:31 Durée =
Fonctions Imbriquées
0.003 secs
- 12 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
test.html:32
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
42 43 44 45 46 47
61 62 63 64 65 66
80 81 82 83 84 85
10
29
48
67
86
test.html:46
AVEC « GOTO LABEL »
11
30
49
68
87
12
31
50
69
88
13 14 15
32 33 34
51 52 53
70 71 72
passes.
16
35
54
73
17
36
55
74
18
37
56
75
19
38
57
76
20
39
58
77
21
40
59
78
22
41
60
79
test.html:49
(11) [7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27]
(8) [1, 25, 3, 85, 7, 9, 15, 75]
test.html:65
(14) [7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27, 25, 85, 75]
" .not.included "
(8) [1, 25, 3, 85, 7, 9, 15, 75]
test.html:67 Durée =
test.html:68
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
42 43 44 45 46 47
61 62 63 64 65 66
80 81 82 83 84 85
10
29
48
67
86
0.002 secs
11
30
49
68
87
12
31
50
69
88
13 14 15
32 33 34
51 52 53
70 71 72
passes.
16
35
54
73
17
36
55
74
18
37
56
75
19
38
57
76
20
39
58
77
21
40
59
78
22
41
60
79
Mais il serait plus intéressant que le label (ici « quitLab: ») puisse
être placé APRÈS les deux boucles imbriquées ce qui serait plus
pratique dans certains cas, mais ça semble impossible même
quand on appelle la fonction (qui contient le label) « onload » :
<script type="text/javascript"> "use strict";
const m2 = [7,3,15,20,1,5,9,15,6,35,27];
const e2 = [1,25,3,85,7,9,15,75];
console.log(m2,e2)
console.log("")
Fonctions Imbriquées
- 13 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
var faux=0;
</script>
<script type="text/javascript"> "use strict";
quitLab:
for(let km=0,kml=m2.length ; km<kml ; km++){
for(let ke=0,kel=e2.length ; ke<kel ; ke++){
if(!(m2.includes(e2[ke]))) {
faux++; break quitLab;
}
else continue;
}
}
</script>
<script type="text/javascript"> "use strict";
function fLabel(){
for(let km=0,kml=m2.length ; km<kml ; km++){
for(let ke=0,kel=e2.length ; ke<kel ; ke++){
if(!(m2.includes(e2[ke]))) {
faux++;
//
//
//
//
//
break quitLab2;
Yandex
Uncaught SyntaxError: Undefined label 'quitLab2'
FireFox
SyntaxError: label not found
}
else continue;
}
}
quitLab2:
console.log("Suite")
}
fLabel();
</script>
Fonctions Imbriquées
- 14 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
Exécution :
06:31:40,315
Array(11) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, … ]
Array(8) [ 1, 25, 3, 85, 7, 9, 15, 75 ]
test.html:6:3
06:31:40,321
SyntaxError: label not found
test.html:30:14
Revenons à nos chers moutons et illustrons la non accessibilité
d’une fonction imbriquée depuis le dehors de la fonction qui
l’englobe.
EXEMPLE 1:
Non accessibilité d’une fonction imbriquée du dehors de sa fonction englobante.
<script type="text/javascript"> "use strict";
function personne(){
function congrats(){
console.log( "Hello");
// Hello
test.html:4:13
}
congrats();
return "Englobante";
}
Fonctions Imbriquées
- 15 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log(personne());
// Englobante
test.html:10:1
console.log(congrats());
// Uncaught ReferenceError:
//
congrats is not defined
console.log(personne.congrats());
// Uncaught TypeError:
//
personne.congrats is not a function
</script>
On peut toutefois contourner certaines de ces limitations en faisant que la fonction englobante renvoie un pointeur sur (=
adresse de) la fonction imbriquée, permettant de l’appeler de
l’extérieur de la fonction englobante, l’adresse renvoyée pouvant
éventuellement
être stockée dans une variable.
EXEMPLE 2:
<script type="text/javascript">
function personne(p){
function congrats(c){
console.log(p,c);
}
"use strict";
console.log("Appel interne de congrats('Kibinda')")
congrats("Kibinda");
// Bonjour Kibinda
test.html:4:13
return congrats;
}
const r = personne("Bonjour");
Fonctions Imbriquées
- 16 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log("Appel externe de r('Koye')")
r("Koye"); // Bonjour Koye
test.html:4:13
</script>
Exécution :
Appel interne de congrats('Kibinda')
Bonjour Kibinda
Appel externe de r('Koye')
Bonjour Koye
test.html:8:9
test.html:4:13
test.html:14:1
test.html:4:13
Les membres d’une fonction ont une portée/visibilité locale (limitée
au bloc de cette fonction) : pas accessibles du dehors de la fonction.
Vous pouvez normalement vous arranger pour éventuellement
appeler la fonction imbriquée seulement du sein-même de la fonction englobante. Vous l’exécutez bien sûr, mais pas du dehors de
la fonction englobante.
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
Fonctions Imbriquées
- 17 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
sx.toLowerCase().startsWith("h"))
{
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F"))
{
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
recommendation(gender);
/////////////////////////////////
}
personne(1993,"");
// NIHIL.
personne(1953,"");
// SEXE VIDE. test.html:22:11
personne(1953,"H");
// Attention! Âge 65 > 50 ans!
// Veillez à L'ANDROPAUSE
personne(1953,"F");
// Attention! Âge 65 > 50 ans!
// Veillez à LA MÉNOPAUSE
</script>
test.html:15:11
test.html:19:11
Une façon de contourner cette restriction est de créer au sein de
la fonction englobante un membre (propriété) portant le même
nom que la fonction englobante, cette propriété servira de « clé »
pour accéder à la fonction imbriquée, sans le mot-clé var, ni le
Fonctions Imbriquées
- 18 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
mot-clé this.
<script language="JavaScript"> "use strict";
function personne(dn){
let age=(new Date()).getFullYear() - dn
function recommandation(sx){
if(!sx) sx="";
if(age>50){
const msg="Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
personne.rec = recommandation;
/////////////////////////////////
}
personne(1953);
personne.rec("Homme");
// Attention! Âge [65] > 50 ans!
// Veillez à L'ANDROPAUSE
</script>
test.html:11:16
Une autre façon d’appeler la fonction imbriquée du dehors de la
fonction englobante est de faire de la fonction imbriquée une méFonctions Imbriquées
- 19 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
thode de la fonction englobante, avec le mot-clé this. On crée là
un constructeur d’objet. Ensuite créer une instance de la fonction
englobante, et appeler la fonction imbriquée comme méthode de
l’instance.
<script language="JavaScript"> "use strict";
function personne(dn){
let age=(new Date()).getFullYear() - dn
// age === var locale, pas propriété
/*
// Vous pouvez accéder à une propriété en dehors du constructeur, du sein de ses instances.
// Mais vous ne pouvez accéder à une variable locale que
du sein de la fonction (ici le constructeur).
*/
this.recommandation = function(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h"))
{
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
}
const inst = new personne(1953);
Fonctions Imbriquées
- 20 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
inst.recommandation("Femme");
// Attention! Âge 65 > 50 ans! Veillez à LA MÉNOPAUSE
</script>
Au besoin, vous pouvez utiliser la technique de curry function, on
parle alors de fermeture (= closure):
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
return recommendation;
/////////////////////////////////
}
let emissaire=personne(1953);
var rec = emissaire("Homme")
// Attention! Âge 65 > 50 ans! Veillez à L'ANDROPAUSE
var rec = emissaire("Femme")
Fonctions Imbriquées
- 21 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
// Attention! Âge 65 > 50 ans! Veillez à LA MÉNOPAUSE
var rec = emissaire("")
// SEXE VIDE.
</script>
Vous pouvez aussi appeler la fonction englobante et la fonction
imbriquée dans une même instruction, par une succession de parenthèses :
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
let L=50;
const msg="Attention! Âge "+age+
` ${age>=50?'>=':'<'} ` + L+" ans! Veillez à";
if(age>=(L=50)){
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log(msg,"...Sexe Vide.".toUpperCase())
}
}
else console.log(
msg,"...VoTrE jeUnesSe.".toUpperCase()
)
}
return recommendation;
Fonctions Imbriquées
- 22 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
}
let emissaire;
/////////////////////////////////
emissaire=personne(1963)("Homme")
// Attention! Âge 55 >= 50 ans! Veillez à L'ANDROPAUSE
emissaire=personne(1973)("Mâle")
// Attention! Âge 45 < 50 ans! Veillez à ...VOTRE JEUNESSE.
emissaire=personne(1953)("")
// Attention! Âge 65 >= 50 ans! Veillez à ...SEXE VIDE.
emissaire=personne(1919)("Femelle")
// Attention! Âge 99 >= 50 ans! Veillez à LA MÉNOPAUSE
emissaire=personne(1969)()
// Attention! Âge 49 < 50 ans! Veillez à ...VOTRE JEUNESSE.
emissaire=personne(1968 , "Femme")()
// Attention! Âge 50 >= 50 ans! Veillez à ...SEXE VIDE.
emissaire=personne()("Femme",1923)
// Attention! Âge NaN < 50 ans! Veillez à ...VOTRE JEUNESSE.
/////////////////////////////////
</script>
Vous pouvez aussi faire en sorte de n’appeler la fonction « recommandation » que sous certaines conditions selon le statu renvoyé par la fonction englobante.
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
Fonctions Imbriquées
- 23 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
return [recommendation , age];
/////////////////////////////////
}
let emissaire=personne(1953);
if(emissaire[1]>50) {
var rec = emissaire[0]("")
// SEXE VIDE.
var rec = emissaire[0]("Homme")
// Attention! Âge 65 > 50 ans! Veillez à L'ANDROPAUSE
var rec = emissaire[0]("Femme")
// Attention! Âge 65 > 50 ans! Veillez à LA MÉNOPAUSE
}
</script>
Voyons dans ce dernier cas l’anatomie (la configuration interne)
de la variable array « emissaire » :
Fonctions Imbriquées
- 24 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
Avec la méthode
« Object.getOwnPropertyDescriptors(emissaire) » :
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
return [recommendation , age];
/////////////////////////////////
}
let emissaire=personne(1953);
console.dir(Object.getOwnPropertyDescriptors(emissaire))
//
// Object
A
0:{
value: ƒ, writable: true,
enumerable: true, configurable: true
}
B
1:{
value: 65, writable: true,
enumerable: true, configurable: true
}
Fonctions Imbriquées
- 25 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
C
D
JavaScript Tome-VI
length:{
value: 2, writable: true,
enumerable: false, configurable: false
}
__proto__:Object
</script>
On peut aussi parcourir (énumérer) les propriétés de l’array
« emissaire » avec la commande « for ... in » :
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
/////////////////////////////////
return [recommendation , age];
/////////////////////////////////
}
let emissaire=personne(1953);
for(const key in emissaire){
Fonctions Imbriquées
- 26 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
console.log(key, emissaire[key])
}
/*
0
ƒ recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase(…
1
65
*/
</script>
Maintenant, parcourons l’array retournée, avec un
ITÉRATEUR :
<script language="JavaScript"> "use strict";
function personne(dn,gender){
let age=(new Date()).getFullYear() - dn
function recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg="Attention! Âge "+age+" > 50 ans!
Veillez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
console.log(msg,"l'andropause".toUpperCase())
}
else if(sx.startsWith("F")) {
console.log(msg,"la ménopause".toUpperCase())
}
else {
console.log("Sexe Vide.".toUpperCase())
}
}
}
Fonctions Imbriquées
- 27 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
/////////////////////////////////
return [recommendation , age];
/////////////////////////////////
}
let ITERABLE=personne(1953);
const ITERATOR = ITERABLE[Symbol.iterator]();
for(let key in ITERABLE)console.log(ITERATOR.next())
/*
Object { value: recommendation(), done: false }
Object { value: 65, done: false }
*/
console.log(ITERATOR.next())
// Object { value: undefined, done: true }
console.log(ITERATOR.next())
// Object { value: undefined, done: true }
</script>
I. Quant à appeler une fonction en cliquant un lien, il y a
deux possibilités :
1er L’hypertexte sert seulement à appeler une fonction. La
chose est alors très facile :
<a href="javascript:
console.dir(Object.getOwnPropertyDescriptors(HTMLDivElemen
t))">
Without Following Link
</a>
2e L’hypertexte DOIT APPELER une fonction mais aussi jouer
son rôle habituel, c’est-à-dire « suivre le lien » = aller à un
Fonctions Imbriquées
- 28 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
emplacement spécifique de la page en cours ou ouvrir la page
pointée. Les choses sont alors un peu corsées, mais encore
toujours facile :
<a href="javascript:my_func('http://diasmath.blogg.org')">
Following Link
</a>
<script language="JavaScript">
function my_func(s) {
console.dir(Object.getOwnPropertyDescriptors(Document));
window.open(s)
}
</script>
II. Si l’hypertexte doit être activé par l’événement « onclick »
pour appeler une fonction externe à l’élément ou exécuter
un javascript local, son « href » doit être une simple dièse ,
qu’il doive ou pas suivre de lien.
<a href="#"
onclick="javascript:my_func('http://diasmath.blogg.org')">
Lien Dièse
</a>
<script language="JavaScript">
function my_func(s) {
console.dir(Object.getOwnPropertyDescriptors(Document));
window.open(s)
}
</script>
Parfois aussi ça marche sans le mot-clé « javascript» :
Fonctions Imbriquées
- 29 / 31
jeudi, 4. avril 2019 (10:49 )
J.D.B. DIASOLUKA Nz. Luyalu
JavaScript Tome-VI
<a href="#"
onclick="my_func('http://diasmath.blogg.org')">
Lien Dièse
</a>
<script language="JavaScript">
function my_func(s) {
console.dir(Object.getOwnPropertyDescriptors(Document));
window.open(s)
}
</script>
Mots-clés :
fonctions imbriquées, curry ,closure, objets de première classe,
objet Function, callable object, objets de premier ordre, objets
de première classe, fonction englobante, variable locale,
instances, constructeur, curry, fermeture, closure,
getOwnPropertyDescriptors, hypertexte
jeudi, 4. avril 2019 (10:49 ).
Fonctions Imbriquées
- 30 / 31
jeudi, 4. avril 2019 (10:49 )
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)
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 - 995624714 - 902263541 - 813572818
[email protected]
Fonctions Imbriquées
- 31 / 31
jeudi, 4. avril 2019 (10:49 )