You are on page 1of 27

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 premiè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 inverse-
ment (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 fonc-


tions ordinaires imbriquées [tout comme elle peut avoir
des variables locales propres]. Mais une fonction imbri-
quée ne peut être appelée directement que du sein de la
fonction qui l’englobe, jamais du dehors de cette fonc-
tion englobante. Ceci s’applique aussi aux variables lo-
cales propres à la fonction.

Donc fonctions imbriquées et variables propres d’une


fonction ne sont pas directement accessible du dehors de
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
la fonction englobante, sauf si on les retourne implicite-
ment avec un « return » .

Mais rappelez-vous que « return » ) ne peut retourner


qu’une et une seule valeur, et que pour retourner plu-
sieurs 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
// fonction anonyme imbriquée est récupérée
// par la variable « retval ».

console.log(
retval[0] + "^" + exp + " = " + retval[1]
);
</script>

Exécution:

Fonctions Imbriquées - 2 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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().

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]
);

Fonctions Imbriquées - 3 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
// 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();

// 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() test.html:66:3


// fext()
// length: 1
// name: ""
// <prototype>: function ()

// Nous voyons bien ci-dessus que notre


// pointeur « rtvf » représente bien (pointe sur)
// notre fonction englobante externe « fext() ».

Fonctions Imbriquées - 4 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI

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() ».

</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 perfor-
mant, 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

Fonctions Imbriquées - 5 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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 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.")
Fonctions Imbriquées - 6 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
</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,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 « go-


to » s’arrêtent dès qu’elles rencontrent le premier

Fonctions Imbriquées - 7 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
élément de l’array « e » (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 test.html:31:3


07:25:23,845 1 2 passes. 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
Array(12) [ 7, 3, 15, 20, 1, 5, 9, 15, 6, 35, 27, 25 ]
.not.included

Fonctions Imbriquées - 8 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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;
}
}
// 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")
Fonctions Imbriquées - 9 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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)
console.log("Durée = ",((new Date())-d2)/1000+" secs")
console.log(tmp+" passes.")
</script>

Exécution :

1. Les deux versions sans « goto » et avec « go-


to » ne s’arrêtent que quand ils ont fini de parcou-
rir tous les éléments de l’array « e »
(d’échantillons) en les comparant avec les éléments de
Fonctions Imbriquées - 10 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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 = 0.003 secs

test.html:32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 passes.

test.html:46 AVEC « GOTO LABEL »


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]

Fonctions Imbriquées - 11 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
test.html:67 Durée = 0.002 secs

test.html:68
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 passes.

Mais il serait plus intéressant que le label (ici « qui-


tLab: » ) puisse être placé APRÈ S les deux boucles imbri-
qué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("")
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++){

Fonctions Imbriquées - 12 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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>

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 accessi-


bilité d’une fonction imbriquée depuis le dehors de la
fonction qui l’englobe.

EXEMPLE 1:
Fonctions Imbriquées - 13 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI

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";
}

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"> "use strict";


function personne(p){
function congrats(c){
console.log(p,c);
}
Fonctions Imbriquées - 14 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI

console.log("Appel interne de congrats('Kibinda')")


congrats("Kibinda");
// Bonjour Kibinda test.html:4:13
return congrats;
}

const r = personne("Bonjour");
console.log("Appel externe de r('Koye')")
r("Koye"); // Bonjour Koye test.html:4:13

</script>

Exécution :

Appel interne de congrats('Kibinda') test.html:8:9


Bonjour Kibinda test.html:4:13
Appel externe de r('Koye') test.html:14:1
Bonjour Koye test.html:4:13

Les membres d’une fonction ont une portée/visibilité lo-


cale (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 - 15 / 27 samedi, 24. novembre 2018 (1:05 )
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 test.html:15:11

personne(1953,"F");
// Attention! Âge 65 > 50 ans!
// Veillez à LA MÉNOPAUSE test.html:19:11
</script>

Une façon de contourner cette restriction est de créer au


sein de la fonction englobante un membre (propriété) por-
tant le même nom que la fonction englobante, cette pro-
priété servira de « clé » pour accéder à la fonction im-
briquée, sans le mot-clé var, ni le mot-clé this.

<script language="JavaScript"> "use strict";


function personne(dn){
let age=(new Date()).getFullYear() - dn

Fonctions Imbriquées - 16 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
function recommandation(sx){
if(!sx) sx="";
if(age>50){
const msg="Attention! Âge "+age+" > 50 ans! Veil-
lez à";
if(sx.toLowerCase().startsWith("m") ||
sx.toLowerCase().startsWith("h")) {
con-
sole.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 test.html:11:16
</script>

Une autre façon d’appeler la fonction imbriquée du dehors


de la fonction englobante est de faire de la fonction im-
briquée une mé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 cons-

Fonctions Imbriquées - 17 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
tructeur, 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);

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") ||
Fonctions Imbriquées - 18 / 27 samedi, 24. novembre 2018 (1:05 )
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())
}
}
}

/////////////////////////////////
return recommendation;
/////////////////////////////////
}

let emissaire=personne(1953);
var rec = emissaire("Homme")
// Attention! Âge 65 > 50 ans! Veillez à L'ANDROPAUSE

var rec = emissaire("Femme")


// 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 suc-
cession 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")) {
Fonctions Imbriquées - 19 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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;
}

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 JEU-
NESSE.

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 JEU-
NESSE.

emissaire=personne(1968 , "Femme")()
// Attention! Âge 50 >= 50 ans! Veillez à ...SEXE VIDE.

emissaire=personne()("Femme",1923)
// Attention! Âge NaN < 50 ans! Veillez à ...VOTRE JEU-
NESSE.
/////////////////////////////////
</script>

Vous pouvez aussi faire en sorte de n’appeler la fonction


Fonctions Imbriquées - 20 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
« 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

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 - 21 / 27 samedi, 24. novembre 2018 (1:05 )
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
}
C length:{
value: 2, writable: true,
enumerable: false, configurable: false
Fonctions Imbriquées - 22 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
}
D __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){
console.log(key, emissaire[key])
}
/*
0 ƒ recommendation(sx){
if(!sx) sx="";
if(age>50){
const msg =
"Attention! Âge "+age+" > 50 ans! Veillez à";
Fonctions Imbriquées - 23 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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())
}
}
}
/////////////////////////////////
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 }
*/

Fonctions Imbriquées - 24 / 27 samedi, 24. novembre 2018 (1:05 )


J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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
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
Fonctions Imbriquées - 25 / 27 samedi, 24. novembre 2018 (1:05 )
J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-VI
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» :

<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

samedi, 24. novembre 2018 (1:05 ).

Fonctions Imbriquées - 26 / 27 samedi, 24. novembre 2018 (1:05 )


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

diasfb@mail2world.com

Fonctions Imbriquées - 27 / 27 samedi, 24. novembre 2018 (1:05 )

You might also like