27 28 Funzioni 1
Una funzione, chiamata anche procedura, è un blocco di istruzioni associate ad un’identificatore (nome funzione) che viene dichiarato subito dopo la keyword function .
Per chiamare una funzione basta semplicemente scrivere il suo nome seguito dalle parentesi tonde.
In quel momento il normale flusso del codice va in pausa, per eseguire prima il codice dentro a quella funzione, per poi proseguire nel punto immediatamente successivo alla chiamata della funzione.
function f() { writeln("Sono stata chiamata"); writeln("Dopo questa ritorno!"); }
ora chiamiamo la funzione appena creata
f();
La funzione f() , richiama un’ altra funzione che avevamo visto agli inizi
const br = "<br />"; function writeln(messaggio) { document.write(messaggio + br); }
Possiamo tranquillamente mettere la funzione writeln in fondo al nostro codice.
Se mettiamo in fondo anche la costante br otterremo un errore undefined , perché le variabili e le costanti devono essere dichiarate prima.
writeln("Sono stata chiamata");
nel richiamare la funzione writeln specifico un argomento ( sono stata chiamata ) , in questo caso una stringa . Questo argomento prende il nome di parametro attuale.
Il valore del parametro attuale viene copiato nel parametro formale
function writeln(messaggio)
Nel nostro esempio, messaggio è il parametro formale, chiamato anche segnaposto, signature o firma , che prende temporaneamente il valore del parametro attuale ( sono stata chiamata ).
Approfondiamo il discorso tra i parametri :
function media(risultato, n1, n2, n3) { risultato = (n1+n2+n3) / 3; }
questa è una funzione che calcola la media, ora dichiaro una variabile m e lancio la funzione della media specificando i 3 numeri e m che va a pescare la media dal parametro risultato
let m = 0; media(m, 10, 15, 35); writeln(m);
Il risultato sarà 0, cioè il valore di m, prima e dopo la chiamata della funzione, infatti una funzione NON PUO’ cambiare il valore di una variabile esterna alla funzione, anche indicata come parametro attuale per la sua chiamata e sarebbe assurdo poterlo dare soprattuto per motivi di sicurezza.
La modalità dei passaggio dei parametri vista fino ad adesso è chiamata by value .
Correggiamo il nostro codice
let m = 0; media(10, 15, 35); writeln(m); function media( n1, n2, n3) { m = (n1+n2+n3) / 3; }
Ora funziona , ma sarebbe un errore architetturale notevole, far usare direttamente dentro la funzione una variabile esterna ( m ).
Esistono 2 soluzioni, il primo è usando il return che restituisce il valore
function media( n1, n2, n3) { return (n1+n2+n3) / 3; }
Come possiamo sfruttare una funzione che restituisce un risultato?
o memorizziamo la funzione in una variabile:
m = media(10 , 15 , 35);
o in un’espressione
y = x -4 * media(10 , 15 , 35);
oppure consumiamo il risultato stampandolo al volo
writeln( media(10 , 15 , 35) );
Possiamo anche incontrare più return in una funzione (esempio classico 1 if e 1 else)
Il secondo modo è il passaggio per indirizzo o by reference
var obj = {risultato: 0}; media2(obj, 10, 15, 35); writeln("con obj: " + obj.risultato);
In questo esempio ho creato un oggetto con la sua proprietà risultato (approfondiremo più avanti), ed ecco la funzione a cui passo l’oggetto obj
function media2( obj, n1, n2, n3) { obj.risultato = (n1+n2+n3) / 3; }
quando passo obj il passaggio è sempre per valore, ma in presenza di un oggetto o di un array, la funzione riceve l’indirizzo e a questo punto può modificare il valore di una proprietà (risultato) dell’oggetto. Vediamo lo steso esempio con un array (approfondiremo anche questo più avanti)
var arr = Array(); media3(arr, 10, 15, 35); writeln("con array: " + arr[0]);
e la funzione che assegna in posizione zero dell’array arr il valore (n1+n2+n3) / 3
//riceve e valorizza un elemento di un array function media3( arr, n1, n2, n3) { arr[0] = (n1+n2+n3) / 3 ; }
Come per l’oggetto, quando un array viene passato ad una funzione, è il suo indirizzo che arriva, non l’oggetto in sé . Usare l’array al posto di un oggetto è utile quando devo per esempio far scorrer con un ciclo i suoi indici numerici, a differenza dell’oggetto che usa le property .
Entrambi sono indispensabili ad esempio quando una funzione deve restituire più risultati, il semplice return non basterebbe, tipo un’equazione di secondo grado :
function eqIIgrado_Obj( a, b, c) { var delta = Math.sqrt( b*b - 4*a*c); var x1 = (-b - delta) / 2; var x2 = (-b + delta) / 2; return {x1: x1, x2: x2}; }
funzione che restituisce piú valori in un oggetto (x1 e x2) con oggetto e di seguito la chiamata
var soluzioni = eqIIgrado_Obj(1,5,-24); //x1=3, x2=-24 writeln("x1= " + soluzioni.x1 +", x2=" + soluzioni.x2 );
analogamente con gli array
function eqIIgrado_Arr( a, b, c ) { var delta = Math.sqrt( b*b - 4*a*c); var x1 = (-b - delta) / 2; var x2 = (-b + delta) / 2; return [x1, x2]; }
questa funzione restituisce piú valori in un array. Ed ecco il suo richiamo
soluzioni = eqIIgrado_Arr(1,5,-24); //x1=3, x2=-24 writeln("x1= " + soluzioni[0] +", x2=" + soluzioni[1] );