Skillbook Logo
foto profilo

Skill Factory

Lista post > TypeScript - Lezione 4: Tipi di Funzioni

TypeScript - Lezione 4: Tipi di Funzioni

Gino Visciano | Skill Factory - 03/07/2020 16:33:54 | in Tutorials

In questa lezione vedremo tutti i tipi di funzioni che si possono utilizzare in TypeScript.

Per creare una funzione in  TypeScript dovete utilizzare la sintassi seguente:

function nomeFunzione(elenco argomenti):tipoValoreRestituito {
     // Codice funzione
}

Se la funzione si comporta come una procedura , perché non restituisce nessun valore, come tipoValoreRestituito  dovete usare il tipo void.

Ad esempio la funzione contaFinoADieci è di tipo void, perché è una procedura che visualizza un numero da 1 fino a 10:


function contaFinoADieci():void {
    for(let x:number=1;x<=10;x++){
        console.log(x);
    }
}
// Esegue contaFinoADieci
contaFinoADieci();
 

La parola chiave let indica che la variabile x può essere usata solo nel blocco for, al di fuori del blocco for non è visibile. Per usare la x anche al di fuori del blocco for dovete usare la parola chiave var

Anche la funzione contaFinoAMax è una procedura, ma attraverso l'argomento max permette di visualizzare un numero da 1 ad un valore predefinito.


function contaFinoAMax(max:number):void {
    for(let x:number=1;x<=max;x++){
        console.log(x);
    }
}
// Esegue contaFinoAMax e conta fino a 20
contaFinoAMax(20);
 

Quando la funzione  restituisce un valore attraverso il comando return, il  tipoValoreRestituito deve essere dello stesso tipo, come mostra l'esempio seguente:


function divisione(dividendo:numberdivisore:number):number {
    var risultato:number;
    risultato=dividendo/divisore;
    return risultato;
}
 

 

DIFFERENZA TRA FUNZIONI CON PASSAGGIO PER VALORE E PASSAGGIO PER RIFERIMENTO

Le funzioni sono task di programmazione che eseguono operazioni specifiche quando vengono eseguite.

Se necessario possono ricevere argomenti in input e restituire un argomento come output, naturalmente se non sono di tipo  void.  

L'immagine seguente mostra il comportamento di una funzione che riceve n argomenti in ingresso (input)  e ne restituisce uno in uscita (output).

Block box significa che se una funzione riceve in input gli  stessi argomenti, fornisce sempre lo stesso risultato come output.

Gli argomenti delle funzioni, sia in input, sia in output, possono essere passati per valore oppure per riferimento

Quando passate un argomento per valore state passando il contenuto di una variabile

Quando il passaggio avviene per riferimento state passando l'indirizzo di un array oppure di un oggetto in cui sono contenuti i valori.

Questa differenza è molto importante perché  se il passaggio degli argomenti avviene per valore, utilizzate una copia dei valori originali, mentre se il passaggio degli argomenti avviene per riferimento, attraverso l'indirizzo lavorate direttamente  con i valori degli array o degli oggetti originali. 

L'immagine seguente descrive un esempio di passaggio per valore, in questo caso gli argomenti della funzione divisione ricevono una copia del contenuto delle variabili dividendo e divisore.

L'immagine seguente descrive un esempio di passaggio per riferimento, in questo caso l'argomento della funzione calcolaQuadrato riceve una copia del riferimento (indirizzo) dell'array di interi numeri, attraverso il riferimento può modificare direttamente il contenuto dell'array.

Esempio 1

L'esempio seguente mostra che il passaggio per valore permette di copiare il contenuto della variabile originale nella variabile indicata come argomento. Modificando il contenuto della variabile indicata come argomento della funzione, il contenuto della variabile originale non cambia: 


// passaggio_per_valore.ts
function modificaValore(copiaDiA:number){
    console.log("Funzione modificaValore, valore passato:"+copiaDiA);
    //Modifico copiaDiA;
    copiaDiA=20;
    console.log("Funzione modificaValore, valore modificato:"+copiaDiA);
}
 
//Modulo
var a:number=10;
console.log("Modulo, valore passato alla funzione modificaValore:"+a);
modificaValore(a)
console.log("Modulo, valore dopo l'esecuzione della funzione modificaValore:"+a);
------------------------------------------------------------------------------------
Modulo, valore passato alla funzione modificaValore:10
Funzione modificaValore, valore passato:10
Funzione modificaValore, valore modificato:20
Modulo, valore dopo l'esecuzione della funzione modificaValore:10
 

Con il passaggio per valore, per modificare  il contenuto della variabile originale dovete usare il comando return, come mostra l'esempio seguente:

Esempio 2

 
// passaggio_per_valore_bis.ts
function modificaValore(copiaDiA:number):number{
    console.log("Funzione modificaValore, valore passato:"+copiaDiA);
    //Modifico copiaDiA;
    copiaDiA=20;
    console.log("Funzione modificaValore, valore modificato:"+copiaDiA);
    return copiaDiA;
}
 
//Modulo
var a:number=10;
console.log("Modulo, valore passato alla funzione modificaValore:"+a);
a=modificaValore(a)
console.log("Modulo, valore dopo l'esecuzione della funzione modificaValore:"+a);
------------------------------------------------------------------------------------
Modulo, valore passato alla funzione modificaValore:10
Funzione modificaValore, valore passato:10
Funzione modificaValore, valore modificato:20
Modulo, valore dopo l'esecuzione della funzione modificaValore:20
 

Esempio 3

L'esempio seguente mostra che il passaggio per riferimento permette di copiare l'indirizzo di un array o di un oggetto nella variabile indicata come argomento. Attraverso il riferimento è possibile modificare direttamente il valore della variabile originale: 

 
 
// passaggio_per_riferimento.ts
function modificaValore(rifObjJson:{a:number}){
    console.log("Funzione modificaValore, valore passato:"+rifObjJson.a);
    //Modifico copiaDiA;
    rifObjJson.a=20;
    console.log("Funzione modificaValore, valore modificato:"+rifObjJson.a);
}
 
//Modulo
//Dichiarazione di una variabile in cui memorizzare il riferimento di 
//un oggetto di tipo Json
var objJson:{a:number};
//Creazione di un oggetto di tipo Json assegnando il valore 10 all'attributo a 
objJson={a:10}; 
console.log("Modulo, valore passato alla funzione modificaValore:"+objJson.a);
//Passo alla funzione il riferimento (indirizzo) dell'oggetto objJson.
modificaValore(objJson);
console.log("Modulo, valore dopo l'esecuzione della funzione modificaValore:"+objJson.a);
-----------------------------------------------------------------------------------------
Modulo, valore passato alla funzione modificaValore:10
Funzione modificaValore, valore passato:10
Funzione modificaValore, valore modificato:20
Modulo, valore dopo l'esecuzione della funzione modificaValore:20
 

 

FUNZIONI ANONIME

In TypeScript le funzioni possono essere passate  come argomenti ad altre funzioni, utilizzando il loro riferimento

In questo caso non passate un'informazione, ma un comportamento.

Una funzione che riceve in input il riferimento di una funzione viene chiamata funzione superiore.  

Le funzioni anonime sono funzioni che non hanno un nome e possono essere eseguite attraverso il loro riferimento.

Questo tipo di funzione può anche essere passata come argomento ad funzione superiore.

 L'esempio seguente mostra come si crea ed esegue una funzione anonima, utilizzando il metodo log che in questo caso è la funzione superiore.

 
var rifPerimetro=function (latoA:number,latoB:number,latoC:number):number {
    return latoA+latoB+latoC;
}
console.log(rifPerimetro(10,15,20));
----------------------------------------------------------------------------
45
 

 

FUNZIONI LAMBDA

Le funzioni lambda sono particolari tipi di funzioni anonime, quindi anch'esse possono essere passate  come argomenti alle funzione superiori.

La sintassi per creare le funzioni lambda è leggermente diversa da quella usata per le funzioni anonime, perché al posto della parola chiave function si usa l'operatore freccia "=>", come mostra l'esempio seguente:


var rifPerimetro=(latoA:number,latoB:number,latoC:number):number => {
    return latoA+latoB+latoC;
}
console.log(rifPerimetro(10,15,20));
---------------------------------------------------------------------------------------
45

Attenzione, le funzioni lambda e le funzioni anonime, se sono composte da una sola riga di comando, possono essere implementate senza usare le parentesi graffe e senza indicare il return, come mostra l'esempio seguente:


var rifPerimetro=(latoA:number,latoB:number,latoC:number):number => latoA+latoB+latoC;
console.log(rifPerimetro(10,15,20));
---------------------------------------------------------------------------------------
45
 

 

FUNZIONI RICORSIVE

In TypeScript le funzioni sono ricorsive, cioè possono chiamare se stesse. Questa caratteristica è molto importante perché la ricorsività permette di simulare il comportamento di un ciclo while al contrario. 

Per capire l'utilità della ricorsività delle funzioni facciamo alcuni  esempi.

Esempio 4

Visualizzare il contenuto di una array d'interi partendo dall'ultimo valore al primo.

A) Soluzione utilizzando un while.

//inverti_interi.ts
var interi:number[]=[2,10,25,8,80,30,70,5,15,90];
var indice:number=interi.length-1;
while(indice>=0){
    console.log(interi[indice]);
    indice--;
}
-----------------------------------------------------
90
15
5
70
30
80
8
25
10
2

B) Soluzione utilizzando una funzione ricorsiva.

 
//inverti_interi_ricorsivo.ts
function inverti_interi(indice:number){
  if(indice<interi.length-1){
      inverti_interi(indice+1);
   }
   console.log(indice+","+interi[indice]);
}
 
// main
var interi:number[]=[2,10,25,8,80,30,70,5,15,90];
inverti_interi(0);
-------------------------------------------------------
9,90
8,15
7,5
6,70
5,30
4,80
3,8
2,25
1,10
0,2
 

Esempio 5

Calcolare il fattoriale di un numero intero N.
Il fattoriale di un numero intero N è dato dal prodotto di tutti i valori compresi tra 1 ad N, ad esempio il fattoriale di 3 = 1 * 2 * 3 = 6.

 

A) Soluzione utilizzando un while.

 
//fattoriale_while.ts
function fattoriale(numero:number):number{
var totale=1;
while(numero>1){
    totale*=numero;
    numero--;
}
return totale;
}
// main
console.log(fattoriale(5));
-------------------------------------------------
120
 

B) Soluzione utilizzando una funzione ricorsiva.

 
//fattoriale.ts
function fattoriale(numero:number):number{
    if(numero>1){
        numero*=fattoriale(numero-1);
    }else {
        return 1;
    }
    return numero;
}
 
// main
console.log(fattoriale(5));
-------------------------------------------------
120
 

Attenzione, per convenzione, il fattoriale di 0 = 1.

 
//fattoriale.ts
function fattoriale(numero:number):number{
    if(numero>1){
        numero*=fattoriale(numero-1);
    }else {
        return 1;
    }
    return numero;
}
// main
console.log(fattoriale(0));
-------------------------------------------------
1
 
 

 

FUNZIONI CON ARGOMENTI OPZIONALI

In TypeScript si possono creare funzioni con argomenti opzionali, per rendere l'argomento di una funzione opzionale basta inserire un "?" dopo il nome dell'argomento, come mostra l'esempio seguente:

function infoFiguraGeometrica(tipoFigura:string, valoreUno:number,valoreDue?:number,valoreTre?:number){...} 

La dichiarazione della funzione  infoFiguraGeometrica  indica che gli argomenti tipoFigura:stringvaloreUno:number, sono obbligatori e gli argomenti valoreDue?:number,valoreTre?:number sono opzionali.

L'attributo length dell'interfaccia arguments permette do conoscere il numero di argomenti passati ad una funzione con argomenti opzionali. 

Esempio 6

 
// opzionali_01.ts
function infoFiguraGeometrica(tipoFigura:stringvaloreUno:number,valoreDue?:number,valoreTre?:number):void{
var scelta:number=arguments.length;
var perimetro:number,area:number;
// Controllo se tipoFigura è corretto altrimenti controllo se i valori sono maggiori
// di zero
// Scelta=5 imposta il default che corrisponde ad un errore
if(tipoFigura.toLowerCase()!="cerchio" && tipoFigura.toLowerCase()!="quadrato" && 
   tipoFigura.toLowerCase()!="rettangolo" && tipoFigura.toLowerCase()!="triangolo"){
       scelta=5;
}else if(arguments.length==2 && valoreUno<=0){
    scelta=5;
}else if(arguments.length==3 && (valoreUno<=0 || valoreDue<=0)){
    scelta=5
}else if(arguments.length==4 && (valoreUno<=0 || valoreDue<=0 || valoreTre<=0)){
    scelta=5
}
//Controllo se i lati del triangolo sono coerenti altrimenti imposto la scelta=5
if(scelta!=5 && arguments.length==4){
    if(valoreUno>=valoreDue+valoreTre || valoreUno<=valoreDue-valoreTre){
        scelta=5;
    } else if(valoreDue>=valoreUno+valoreTre || valoreDue<=valoreUno-valoreTre){
        scelta=5;
    } else if(valoreTre>=valoreDue+valoreUno || valoreTre<=valoreDue-valoreUno){
        scelta=5;
    } 
}
 
switch(scelta){
    case 2:
        if(tipoFigura.toLowerCase()=="cerchio"){
            perimetro=2*Math.PI*valoreUno;
            area=Math.pow(valoreUno,2)*Math.PI;
            console.log("Tipo figura:"+tipoFigura);
            console.log("Raggio     :"+valoreUno);
            console.log("Perimetro  :"+perimetro);
            console.log("Area       :"+area);
        }   else{
            perimetro=4*valoreUno;
            area=Math.pow(valoreUno,2);
            console.log("Tipo figura:"+tipoFigura);
            console.log("Lato       :"+valoreUno);
            console.log("Perimetro  :"+perimetro);
            console.log("Area       :"+area);
        }
        break;
    case 3:
        perimetro=(2*valoreUno)+(2*valoreDue);
        area=valoreUno*valoreDue;
        console.log("Tipo figura:"+tipoFigura);
        console.log("Lati       :"+valoreUno,valoreDue);
        console.log("Perimetro  :"+perimetro);
        console.log("Area       :"+area);
    break;
    case 4:
        perimetro=valoreUno+valoreDue+valoreTre;
        let sp=perimetro/2;
        area=Math.sqrt(sp*(sp-valoreUno)*(sp-valoreDue)*(sp-valoreTre));
        console.log("Tipo figura:"+tipoFigura);
        console.log("Lati       :"+valoreUno,valoreDue,valoreTre);
        console.log("Perimetro  :"+perimetro);
        console.log("Area       :"+area);
        break;
        default:
            console.log("Errore: Gli argomenti forniti alla funzione non sono esatti")
    } 
}
// main
console.log("----- Gestione Figure Geometriche -----");
infoFiguraGeometrica("Cerchio",10);
console.log("---------------------------------------");
infoFiguraGeometrica("Quadrato",20);
console.log("---------------------------------------");
infoFiguraGeometrica("Rettangolo",10,5);
console.log("---------------------------------------");
infoFiguraGeometrica("Triangolo",10,20,20);


----------------------------------------------------------------------

Tipo figura:Cerchio
Raggio     :10
Perimetro  :62.83185307179586
Area       :314.1592653589793
---------------------------------------
Tipo figura:Quadrato
Lato       :20
Perimetro  :80
Area       :400
---------------------------------------
Tipo figura:Rettangolo
Lati       :10 5
Perimetro  :30
Area       :50
---------------------------------------
Tipo figura:Triangolo
Lati       :10 20 20
Perimetro  :50
Area       :96.82458365518542

 

Un argomento opzionale a cui non viene passato nulla contiene il valore undefined, come mostra l'esempio seguente:

 
//opzionali_02.ts
function infoArgomenti(a?:number,b?:number){
    console.log("Argomenti:"+arguments.length)
    if(a==undefined && b==undefined){
      console.log("Non hai fornito argomenti");
      console.log("a=" +a);
      console.log("b=" +b);
  } else if (b==undefined){
        console.log("Hai fornito un solo argomento");
        console.log("a=" +a);
        console.log("b=" +b);
    } else{
        console.log("Hai fornito due argomenti");
        console.log("a=" +a);
        console.log("b=" +b);
    }
}
// main
infoArgomenti();
infoArgomenti(10);
infoArgomenti(10,20);
 
---------------------------------------------------------
Argomenti:0
Non hai fornito argomenti
a=undefined
b=undefined
Argomenti:1
Hai fornito due argomenti
a=10
b=undefined
Argomenti:2
Hai fornito due argomenti
a=10
b=20
 

 

Per passare ad una funzione con argomenti opzionali, gli argomenti richiesti, utilizzando i nomi degli argomenti,  dovete usare un'interfaccia e passare gli argomenti alla funzione con la notazione JSON, come mostra l'esempio seguente:

 
//opzionali_03.ts
interface Parametri{
    a?:number;
    b?:number;
}
function infoArgomenti(parametri:Parametri){
    if(parametri.a==undefined && parametri.b==undefined){
      console.log("Non hai fornito argomenti {}");
      console.log("a=" +parametri.a);
      console.log("b=" +parametri.b);
  } else if (parametri.a==undefined){
        console.log("Hai fornito un solo l'argomento a {b:20}");
        console.log("a=" +parametri.a);
        console.log("b=" +parametri.b);
    }else if (parametri.b==undefined){
        console.log("Hai fornito un solo l'argomento b {a:10}");
        console.log("a=" +parametri.a);
        console.log("b=" +parametri.b);
    } else{
        console.log("Hai fornito due argomenti {a:10,b:20}");
        console.log("a=" +parametri.a);
        console.log("b=" +parametri.b);
    }
}
// main
infoArgomenti({});
infoArgomenti({a:10});
infoArgomenti({b:20});
infoArgomenti({a:10,b:20});

---------------------------------------------------------------------
Non hai fornito argomenti {}
a=undefined
b=undefined
Hai fornito un solo l'argomento b {a:10}
a=10
b=undefined
Hai fornito un solo l'argomento a {b:20}
a=undefined
b=20
Hai fornito due argomenti {a:10,b:20}
a=10
b=20

 

 

FUNZIONI CON ARGOMENTI REST

In TypeScript un altro modo per creare funzioni con argomenti opzionali  è quello di utilizzare l'operatore "..." chiamato REST.  L'argomento preceduto dall'operatore REST diventa un array che contiene i valori di tutti gli argomenti passati, come mostrano gli esempi seguenti:

Esempio 7 

// opzionali_01_rest.ts
function infoFiguraGeometrica(tipoFigura:string, ...valori:number[]):void{
var scelta:number=valori.length;
var perimetro:number,area:number;
// Controllo se tipoFigura è corretto altrimenti controllo se i valori sono 
// maggiori di zero
// Scelta=5 imposta il default che corrisponde ad un errore
if(tipoFigura.toLowerCase()!="cerchio" && tipoFigura.toLowerCase()!="quadrato" && 
   tipoFigura.toLowerCase()!="rettangolo" && tipoFigura.toLowerCase()!="triangolo"){
       scelta=5;
}else if(valori.length==1 && valori[0]<=0){
    scelta=5;
}else if(valori.length==2 && (valori[0]<=0 || valori[1]<=0)){
    scelta=5
}else if(valori.length==3 && (valori[0]<=0 || valori[1]<=0 || valori[2]<=0)){
    scelta=5
}
//Controllo se i lati del triangolo sono coerenti altrimenti imposto la scelta=5
if(scelta!=5 && arguments.length==4){
    if(valori[0]>=valori[1]+valori[2] || valori[0]<=valori[1]-valori[2]){
        scelta=5;
    } else if(valori[1]>=valori[0]+valori[2] || valori[1]<=valori[0]-valori[2]){
        scelta=5;
    } else if(valori[2]>=valori[1]+valori[0] || valori[2]<=valori[1]-valori[0]){
        scelta=5;
    } 
}
 
switch(scelta){
    case 2:
        if(tipoFigura.toLowerCase()=="cerchio"){
            perimetro=2*Math.PI*valori[0];
            area=Math.pow(valori[0],2)*Math.PI;
            console.log("Tipo figura:"+tipoFigura);
            console.log("Raggio     :"+valori[0]);
            console.log("Perimetro  :"+perimetro);
            console.log("Area       :"+area);
        }   else{
            perimetro=4*valori[0];
            area=Math.pow(valori[0],2);
            console.log("Tipo figura:"+tipoFigura);
            console.log("Lato       :"+valori[0]);
            console.log("Perimetro  :"+perimetro);
            console.log("Area       :"+area);
        }
        break;
    case 3:
        perimetro=(2*valori[0])+(2*valori[1]);
        area=valori[0]*valori[1];
        console.log("Tipo figura:"+tipoFigura);
        console.log("Lati       :"+valori[0],valori[1]);
        console.log("Perimetro  :"+perimetro);
        console.log("Area       :"+area);
    break;
    case 4:
        perimetro=valori[0]+valori[1]+valori[2];
        let sp=perimetro/2;
        area=Math.sqrt(sp*(sp-valori[0])*(sp-valori[1])*(sp-valori[2]));
        console.log("Tipo figura:"+tipoFigura);
        console.log("Lati       :"+valori[0],valori[1],valori[2]);
        console.log("Perimetro  :"+perimetro);
        console.log("Area       :"+area);
        break;
        default:
            console.log("Errore: Gli argomenti forniti alla funzione non sono esatti")
    } 
}
// main
console.log("----- Gestione Figure Geometriche -----");
infoFiguraGeometrica("Cerchio",10);
console.log("---------------------------------------");
infoFiguraGeometrica("Quadrato",20);
console.log("---------------------------------------");
infoFiguraGeometrica("Rettangolo",10,5);
console.log("---------------------------------------");
infoFiguraGeometrica("Triangolo",10,20,20);

----------------------------------------------------------------------

Tipo figura:Cerchio
Raggio     :10
Perimetro  :62.83185307179586
Area       :314.1592653589793
---------------------------------------
Tipo figura:Quadrato
Lato       :20
Perimetro  :80
Area       :400
---------------------------------------
Tipo figura:Rettangolo
Lati       :10 5
Perimetro  :30
Area       :50
---------------------------------------
Tipo figura:Triangolo
Lati       :10 20 20
Perimetro  :50
Area       :96.82458365518542

 

Esempio 8

 
//rest.ts
class Persona{
    nome:string;
    cognome:string;
    luogoDiNascita:string;
    dataDiNascita:Date;
    sesso:boolean;
    toString():string{
        var gg:number=this.dataDiNascita.getDate(); 
        var mm:number=this.dataDiNascita.getMonth()+1;
        var aaaa:number=this.dataDiNascita.getFullYear();
        var dataValore=gg+"/"+mm+"/"+aaaa;
        var sessoValore:string="";
        if(this.sesso){
            sessoValore="Maschio";
        } else{
            sessoValore="Femmina"
        }
         return this.nome+","+this.cognome+","+this.luogoDiNascita+","+dataValore
                +","+sessoValore;
    }
    constructor(){} // In questo caso il costruttore non contiene codice d'inizializzazione
}
 
function infoArgomentiRest(...parametri:any[]){
    parametri.forEach(parametro =>{
        if(typeof parametro=="number"){
          console.log("number:"+parametro);
        }else if(typeof parametro=="string"){
            console.log("string:"+parametro);
        }else if(typeof parametro=="boolean"){
            console.log("boolean:"+parametro);            
        }else {
            console.log(typeof parametro+":"+parametro);
        }
    })
}
// main
var personaUno:Persona=new Persona();
personaUno.nome="Mario";
personaUno.cognome="Rossi";
personaUno.luogoDiNascita="Milano";
personaUno.dataDiNascita=new Date("12/5/1990");
personaUno.sesso=true;
infoArgomentiRest(10,10.5,"Rossi",true,personaUno);
 
-----------------------------------------------------------------
number:10
number:10.5
string:Rossi
boolean:true
object:Mario,Rossi,Milano,5/12/1990,Maschio
 
 

Nella prossima lezione iniziamo a parlare di Object Oriented in TypeScript, introducendo le Classi e gli Oggetti.


<< Lezione precedente           Lezione successiva >> | Vai alla prima lezione


T U T O R I A L S    S U G G E R I T I


EDUCATIONAL GAMING BOOK (EGB) "H2O"

Nell'era dello SMART LEARNING e di PYTHON i libri non si scrivono, ma si sviluppano, in questo modo chi studia, può sperimentare ed apprendere contemporaneamente; un libro con queste caratteristiche lo possiamo definire un  Educational Gaming Book (EGB).

"H2Oè un EGB che descrive tutte le caratteristiche dell'acqua, la sostanza formata da molecole di H2O, che attraverso il suo ciclo di vita garantisce la sopravvivenza di tutti gli esseri viventi del Pianeta

L'obiettivo dell'EGB è quello di far conoscere ai giovani le proprietà dell'acqua, sotto molti aspetti uniche, per sensibilizzarli a salvaguardare un bene comune raro, indispensabile per la vita


Per il DOWNLOAD di "H2Oclicca qui.

TypeScript JavaScript Angular Skill Factory Skillbook formazione lavoro corsi programmazione Gino Visciano funzioni lambda funzioni ricorsive funzioni anonime funzioni parametri opzionali funzioni argomenti opzionali argomenti rest

Share Button
TOP