Sei sulla pagina 1di 31

Corso di Informatica Multimediale

JavaScript: Esempi

Marco Comini

2021-10-21
JavaScript: Esempi funzioni/6

Bisogna stare attenti alle dichiarazioni in blocchi anonimi (cioè quelli che non sono
il corpo di una funzione) perché JavaScript non li tratta nel modo canonico.
1 var something = 1;
2 { print ( " Inside 1 a : something = " + something );
3 var something = 2;
4 print ( " Inside 1 b : something = " + something );
5 }
6 print ( " Outside 1: something = " + something );
7 print ( " Outside 1: somethingElse = " + somethingElse );
8 { var somethingElse = 4;
9 }
10 print ( " Outside 2: somethingElse = " + somethingElse );
11 function block1 () {
12 print ( " Inside 2 a : something = " + something );
13 var something = 3;
14 print ( " Inside 2 b : something = " + something );
15 }
16 block1 ();
17 print ( " Outside 3: something = " + something );

Marco Comini Informatica Multimediale 2021-10-21 1 / 28


JavaScript: Esempi funzioni/7

le primitive non sono keywords


1 function alertIsPrint ( value ) {
2 var alert = print ;
3 alert ( value );
4 }
5

6 alert ( " Ciao 1 " );


7 alertIsPrint ( " Ciao 2 " );

Marco Comini Informatica Multimediale 2021-10-21 2 / 28


Corso di Informatica Multimediale
Linguaggi di programmazione: Strutturare i dati

Marco Comini

2021-10-21
Strutturare i dati

Definizione (Tipo di dato)


Un tipo di dato è una collezione di valori omogenei ed effettivamente
presentati dotata di un suo insieme di operazioni che manipolano tali valori.
effettivamente presentati = si possono
scrivere
nominare
memorizzare

Due categorie
Tipi semplici
Booleani, Caratteri, Interi, Virgola mobile
Unit (Void)
Enumerazioni
Intervalli
Tipi composti
Record, record varianti
Array
Insiemi
Puntatori
Marco Comini Informatica Multimediale 2021-10-21 3 / 28
Tipi semplici

Unit (Void)
Contiene un unico valore (detto unità) e non ci sono operazioni
Intervalli
Un insieme di tutti i numeri interi fra un minimo e un massimo.
Si implementano come un normale numero intero ma si controlla a tempo
d’esecuzione che il valore sia contenuto nell’intervallo.
Nei linguaggi in cui si hanno i tipi intervallo gli indici degli array sono di questo
tipo.
Enumerazioni
Si dichiarano esplicitamente tutti i nomi dei possibili valori. Ad esempio
1 type Courses = In f o rm a t i ca _ m ul t i me d i al e
2 , M a te ma ti c a_ e_ st a ti st ic a
3 , Sociologia_della_comunicazione
A volte si hanno le operazioni successore e predecessore.

Marco Comini Informatica Multimediale 2021-10-21 4 / 28


Tipi composti: Record

I record (anche chiamati struct) sono identificati da un insieme di nomi, detti


campi (field), associati ad un tipo.
1 record person {
2 name : string ;
3 surname : string ;
4 age : int ;
5 }

Per ogni nome viene riservato uno spazio di memoria adatto a contenere un
valore del tipo specificato

L’unica operazione che è sempre disponibile è l’accesso ad un campo


mediante un nome.
La sintassi tipicamente è l-expr . nome

Marco Comini Informatica Multimediale 2021-10-21 5 / 28


Tipi composti: Record Varianti
Anche i record varianti sono identificati da un insieme di nomi, detti campi
(field), associati ad un tipo.
1 variant_record career_status {
2 study_year : int ;
3 graduated : int ; }

In ogni momento viene mantenuto il valore per uno solo fra i nomi specificati.
Si mantiene inoltre un tag che permette di identificare qual’è il nome attivo.
Viene riservato uno spazio di memoria pari al massimo delle dimensioni di
tutti i tipi specificati più lo spazio per il tag.
I valori del tag del record variante implicitamente sono un enumerato.
Si usa spesso in combinazione con un costrutto case, come
1 case x . tag {
2 study_year : ...
3 graduated : ... }

In alcuni linguaggi abbiamo una variante che viene chiamata union in cui non
si memorizza il tag (perdendo ogni controllo).
Marco Comini Informatica Multimediale 2021-10-21 6 / 28
Tipi composti: Array/1

Gli array di n elementi di tipo τ sono una collezione omogenea di n valori di


tipo τ che vengono riferiti mediante un indice numerico intero o — quando
possibile — sono valori di un intervallo.
Vengono implementati in modo molto efficiente sfruttando le modalità di
accesso diretto alla memoria delle macchine fisiche.
Le dichiarazioni di variabili di tipo array hanno nei vari linguaggi diverse
varianti. Ad esempio
[10]int array
int[10] array
int array[10]
Possono essere multidimensionali. Ad esempio
[10][20]int array
int[10][20] array
int[10,20] array
int array[10][20]

Marco Comini Informatica Multimediale 2021-10-21 7 / 28


Tipi composti: Array/2

In (quasi?) tutti i linguaggi per accedere ai valori di array “monodimensionali”


(= array di tipi semplici) si usa la notazione l-expr [ r-expr ] .
I valori che possono essere assunti dall’indice
se il tipo dell’indice è un intervallo sono tutti quelli dell’intervallo
altrimenti, detta n la dimensione dell’array, ci sono due varianti
▶ I valori da 1 a n
▶ I valori da 0 a n − 1 (la più frequente)

Ad esempio, in un linguaggio in cui il primo elemento degli array ha indice 0,


1 [5] int array ;
2 int k =2;
3 array [3* k -2] = 8;
4 array [1] = 7;
produce l’array

? 7 ? ? 8
0 1 2 3 4

Marco Comini Informatica Multimediale 2021-10-21 8 / 28


Tipi composti: Array/3

Per array “multidimensionali” (array di array di qualche tipo) ci sono due


varianti principali
l-expr [ r-expr ] . . . [ r-expr ]
l-expr [ r-expr , . . . , r-expr ]

Ad esempio, in un linguaggio in cui il primo elemento degli array ha indice 0,


1 [3][5] int matrix ;
2 matrix [2][4] = 8;
3 matrix [1][1] = 7;
produce la matrice

0 1 2 3 4
0 ? ? ? ? ?
1 ? 7 ? ? ?
2 ? ? ? ? 8

Marco Comini Informatica Multimediale 2021-10-21 9 / 28


Tipi composti: Insiemi

Gli insiemi di elementi di tipo τ sono una collezione a dimensione variabile di


valori di tipo τ che implementano “gli insiemi della matematica”
non conta l’ordine
non ci sono duplicati
su cui si possono eseguire le operazioni tipiche di un insieme
intersezione
unione
inserimento di un elemento
test di appartenenza

Si riescono a implementare in modo molto efficiente gli insiemi di valori interi


in intervalli “piccoli”, tipicamente 0–64, 0–128, 0–256

Marco Comini Informatica Multimediale 2021-10-21 10 / 28


Tipi composti: Puntatori

I puntatori di tipo τ sono l-values che riferiscono celle di memoria che


contengono valori di tipo τ . Le operazioni sono
dereferenziazione (dereferencing): dato un puntatore p , *p accede al valore
“puntato” (riferito).
referenziazione (referencing): data una l-expr l (di tipo τ ), & l ne determina
l’l-value (che quindi è un valore per un puntatore di tipo τ ).
confronto di uguaglianza
Si possono usare per costruire strutture dati dinamiche (come grafi, alberi,
liste) che non hanno una dimensione iniziale prefissata e cambia nel tempo.
I puntatori possono essere usati per simulare il passaggio di parametri per
riferimento nei linguaggi che non lo offrono come meccanismo nativo.
Alcuni linguaggi offrono delle operazioni aritmetiche sui puntatori (si parla di
aritmetica dei puntatori).
L’uso in modo indiscriminato dei puntatori conduce a errori di
programmazione difficili da individuare.
Per questo motivo molti linguaggi ne limitano l’uso.

Marco Comini Informatica Multimediale 2021-10-21 11 / 28


Equivalenza dei tipi
Ci sono due regole di equivalenza di tipi canoniche:
per nome: due tipi sono equivalenti per nome solo se hanno lo stesso nome
strutturale: la (minima) relazione d’equivalenza ≈ tale che
1 un nome di tipo è equivalente a se stesso (τ ≈ τ );
2 se un tipo τ è introdotto con una definizione type τ = espressione-di-tipo,
allora τ è equivalente a espressione-di-tipo (τ ≈ espressione-di-tipo);
3 se due tipi sono costruiti applicando lo stesso costruttore di tipo C a tipi
equivalenti, allora essi sono equivalenti (τ ≈ τ̂ =⇒ C(τ ) ≈ C(τ̂ )).
Due tipi sono equivalenti se hanno la stessa struttura, cioè quando,
sostituendo tutti i nomi con le relative definizioni, si ottengono tipi identici.
Ad esempio, considerando le definizioni
1 type T1 = int ; 1 type T4 = record {
2 type T2 = char ; 2 int a ;
3 type T3 = record { 3 char b ;
4 T1 a; 4 }
5 T2 b;
6 }
abbiamo che T3 è strutturalmente equivalente a T4
Marco Comini Informatica Multimediale 2021-10-21 12 / 28
Compatibilità e conversione/1

Diciamo che il tipo τ è compatibile con il tipo τ ′ , se un valore di tipo τ è


ammesso in un qualsiasi contesto in cui sarebbe richiesto un valore di tipo τ ′ .
La relazione di compatibilità è più debole dell’equivalenza, infatti due tipi
equivalenti sono sicuramente compatibili.
La relazione di compatibilità non è simmetrica. Per esempio in molti linguaggi
int è compatibile con float mentre float non è compatibile con int.

In molti linguaggi la correttezza di un assegnamento è regolata con la


compatibilità, piuttosto che l’equivalenza.

Marco Comini Informatica Multimediale 2021-10-21 13 / 28


Compatibilità e conversione/2

Possiamo avere compatibilità quando due tipi hanno la stessa


rappresentazione in memoria.
Ad esempio intervalli e interi.
In questo caso la macchina astratta non deve fare nessuna conversione.

Possiamo avere compatibilità di τ con τ ′ quando esiste una trasformazione


canonica dei valori di τ in valori di τ ′ .
Ad esempio da interi a floating-point.
In questo caso la macchina astratta deve convertire un valore v di tipo τ
applicando detta trasformazione canonica quando v è usato in un contesto di
tipo τ ′ .

Si parla di
conversione implicita o coertion quando la conversione viene fatta nella
macchina astratta, senza che ve ne sia traccia a livello linguistico;
conversione esplicita o cast quando la conversione è indicata nel testo del
programma.

Marco Comini Informatica Multimediale 2021-10-21 14 / 28


Classi ed oggetti/1
Una evoluzione del concetto di tipo di dato è quello delle classi e degli
oggetti (fondamento della programmazione orientata agli oggetti)
Si raggruppa in una zona circoscritta del codice sorgente (chiamata classe),
la dichiarazione delle strutture dati e delle funzioni che operano su di esse.

Definizione (Classi)
Una classe è un costrutto usato come modello per creare oggetti composti da
attributi = la specifica di nomi associati a dei tipi o (altre) classi;
metodi = la specifica di nomi associati a tipi di funzioni.

Solo il tipo dei metodi rimane invariato.


I metodi possono cambiare all’interno di ogni singolo oggetto e possono
riferirsi implicitamente al contenuto dell’oggetto (gli attributi).

Definizione (Istanze)
Una istanza di una classe è un oggetto che contiene valori e funzioni per i nomi
della classe.
Marco Comini Informatica Multimediale 2021-10-21 15 / 28
Classi ed oggetti/2

Le classi costituiscono dei modelli astratti, che a tempo di esecuzione vengono


invocate per istanziare o creare oggetti software relativi alla classe invocata.
Le classi sono un’evoluzione dei record (classe = record + metodi)
oltre ai campi, che vengono chiamati attributi, aggiungiamo i metodi

Una classe è identificabile come un tipo di dato astratto.


Una classe definisce al proprio interno lo stato, i cui dati sono memorizzati
negli attributi, e il comportamento delle funzioni che operano su di esso (i
metodi).
Il medesimo (nome di) metodo in istanze diverse della stessa classe ha sempre
lo stesso tipo ma può avere comportamenti diversi!
Un metodo non può essere invocato a prescindere dall’oggetto a cui
appartiene. Detto diversamente il nome di un metodo è utilizzabile solo in
associazione ad un oggetto. La sintassi tipica è
l-expr . method ( parameters ) .

Marco Comini Informatica Multimediale 2021-10-21 16 / 28


Corso di Informatica Multimediale
Strutturare i dati in JavaScript

Marco Comini

2021-10-21
JavaScript: Oggetti/1

JavaScript è un linguaggio ad oggetti, ma non essendo tipato permette di


creare oggetti mediante espressione diretta senza richiedere la definizione di
una classe.
espressione diretta = si scrivono espressioni che costruiscono direttamente un
oggetto
non serve dichiarare una classe per poter creare un oggetto (anche se non è
proibito)

Oltre ai tipi base (primitivi) in JavaScript esistono solo gli oggetti


Detto diversamente, qualunque valore “costruito” a programma è un oggetto.
Questo vale anche per molti dei tipi primitivi di JavaScript (per esempio gli
array e le stringhe)

Gli oggetti si costruiscono mediante denotazione diretta come sequenza di


associazioni property : value separate da , e delimitate con { e } .
property è un identificatore o una stringa
Ad esempio
var obj = { coordX : 2.4, coordY : 0.3, "in focus": true }

Marco Comini Informatica Multimediale 2021-10-21 17 / 28


JavaScript: Oggetti/2

Il termine proprietà usato da JavaScript indica sia gli attributi che i metodi
nella terminologia della programmazione ad oggetti.

Anche in JavaScript le proprietà che hanno come valore una funzione


vengono chiamati metodi.

Quindi le proprietà che non sono metodi (= che non sono funzioni) sono
esattamente gli attributi nella terminologia della programmazione ad oggetti.

Marco Comini Informatica Multimediale 2021-10-21 18 / 28


JavaScript: Oggetti/3

Abbiamo 2 costrutti per accedere ad una proprietà:


l-expr . property
▶ Il valore di l-expr deve essere un oggetto.
▶ Questa sintassi funziona solo per nomi di proprietà fissi che possono essere
espressi da un identificatore.
Ad esempio obj.coordX .
l-expr [ r-expr ]
▶ Il valore di l-expr deve essere un oggetto.
▶ Qualunque r-expr viene convertita in stringa.
▶ Questa sintassi funziona per nomi di proprietà qualsiasi e può identificare
proprietà diverse di un oggetto (quando r-expr non è una costante).
Ad esempio obj["coordX"] , obj["in focus"] o obj[y] .

l’accesso ad una proprietà in scrittura (= uso a sinistra di un assegnamento)


modifica un eventuale associazione precedente o ne crea una nuova se non
c’era prima.

l’accesso ad una proprietà in lettura vale undefined se non esiste una


associazione.

Marco Comini Informatica Multimediale 2021-10-21 19 / 28


JavaScript: Oggetti/4

Ad esempio
1 var point = { coordY : 2};
2 point . coordX = 0;
3 point . coordY = 0;
4 show ( point );
5 show ( point . coordZ );
produce
1 { coordY : 0 , coordX : 0}
2 undefined

Si può cancellare una proprietà con delete l-expr . property

Marco Comini Informatica Multimediale 2021-10-21 20 / 28


JavaScript: Oggetti/5

Con la keyword this possiamo riferire l’oggetto che invoca una funzione.
Ad esempio
1 var person = {
2 firstName : " John " ,
3 lastName : " Doe " ,
4 fullName : makeFullName
5 };
6

7 function makeFullName () {
8 return this . firstName + " " + this . lastName ;
9 }
10

11 show ( person . fullName ());


produce
1 " John Doe "

Marco Comini Informatica Multimediale 2021-10-21 21 / 28


JavaScript: Classi/1

Se si vuole si può definire una classe con la sintassi


1 class ClassName {
2 constructor (...) { ... }
3 ...
4 }
dove bisogna sempre definire il metodo constructor che si occupa di
costruire un oggetto.
Il numero di argomenti di un costruttore è arbitrario.
Come tutte le altre funzioni in JavaScript può essere variabile.

Per creare una istanza si usa new ClassName ( . . . ) .

Marco Comini Informatica Multimediale 2021-10-21 22 / 28


JavaScript: Classi/2

Ad esempio
1 class Car {
2 constructor ( name , year ) {
3 this . name = name ;
4 this . year = year ;
5 }
6 ageInYear ( year ) {
7 return year - this . year ;
8 }
9 }
10

11 var myCar = new Car ( " Batmobile " , 2018);


12 show ( myCar . ageInYear (2020));
produce 2 .

Marco Comini Informatica Multimediale 2021-10-21 23 / 28


JavaScript: Array/1
Gli array in JavaScript sono oggetti. Hanno però delle peculiarità specifiche.
Si costruiscono con la sintassi [ r-expr , . . . , r-expr ]
(anche solo [] per un array vuoto).
Un array di n elementi ha le proprietà 0, . . . , n − 1 (più precisamente le
stringhe che rappresentano tali numeri).
Quindi con il costrutto per accedere alle proprietà degli oggetti
l-expr [ r-expr ] e la regola di conversione in stringa della r-expr , possiamo
scrivere a[k] identificando la componente k-esima dell’array.
Ad esempio
1 var a = [2 ,3 ,4] , b = [];
2 a [1]=10;
3 b [0]=5;
4 show ( a );
5 show ( b );
produce
1 [2 , 10 , 4]
2 [5]
Marco Comini Informatica Multimediale 2021-10-21 24 / 28
JavaScript: Array/2

Visto che un array è un oggetto, è possibile “scrivere ad un indice che ancora


non esiste”. Quello che succede in più rispetto ad altri oggetti è che, per tutti
gli eventuali indici precedenti che non sono già legati, vengono creati i legami
con il valore undefined . Ad esempio
1 var a = [];
2 a [3]=10;
3 show ( a );
produce
1 [ undefined , undefined , undefined , 10]

Marco Comini Informatica Multimediale 2021-10-21 25 / 28


JavaScript: Array/3
Gli array di JavaScript oltre agli indici hanno anche la proprietà length che
mantiene il numero di elementi dell’array.
Può anche essere direttamente modificata! Se si usa un valore minore della
dimensione attuale allora l’array si accorcia, mentre se è maggiore si
aggiungono degli undefined fino alla nuova misura.
Ad esempio
1 var a = [];
2 show ( a . length );
3 a . length =3;
4 show ( a );
5 a . length =1;
6 show ( a );
produce
1 0
2 [ undefined , undefined , undefined ]
3 [ undefined ]

Marco Comini Informatica Multimediale 2021-10-21 26 / 28


JavaScript: Array/4
Gli array di JavaScript hanno anche svariati altri metodi
fill( value ) Riempie tutto l’array con il valore value. Invece di
1 for ( var k =0; k <200; k ++ ) a [ k ]=22;
si può fare
1 var a = [];
2 a . length =200;
3 a . fill (22);

includes( value ) Verifica se l’array contiene il valore value. Ad esempio


1 var a = [5 ,0 ,9];
2 show ( a . includes (0));
3 show ( a . includes (3));
produce
1 true
2 false

Marco Comini Informatica Multimediale 2021-10-21 27 / 28


JavaScript: Array/5

indexOf( value ) Cerca il valore value nell’array, partendo dall’inizio, e


ritorna la sua posizione.

lastIndexOf( value ) Cerca il valore value nell’array, partendo dalla fine,


e ritorna la sua posizione. Ad esempio
1 var a = [4 , 10 , 5 , 10 , 6];
2 show ( a . indexOf (2));
3 show ( a . indexOf (10));
4 show ( a . lastIndexOf (10));
produce
1 -1
2 1
3 3

Marco Comini Informatica Multimediale 2021-10-21 28 / 28

Potrebbero piacerti anche