I tipi di dato si dividono in due macrocategorie, i tipi primitivi e tutti gli altri. Per conoscere a quale tipo appartiene il valore di una variabile basta usare l'operatore typeof che ritorna il tipo del valore della variabile che si scrive alla sua destra (a volte scritto anche come typeof(a). I tipi primitivi sono:
undefined
Il tipo di dato undefined rappresenta l'assenza di valore, per esempio quando una variabile è stata dichiarata ma non le è ancora stato assegnato un valore. E' l'unico valore che viene assegnato di default dal sistema.
var a; //dichiarazione senza assegnazione, a vale undefined
var b = undefined; //assegnazione esplicita
var c = {};
var d = c.nome; //la proprietà nome non esiste nell'oggetto c, d vale undefined
function test(param) {
//se il parametro non viene passato nel momento della chiamata della funzione questo vale undefined
}
var e = test(); //se il ritorno di una funzione non è specificato, questa ritorna undefined
console.log(typeof a); //"undefined"
console.log(typeof b); //"undefined"
console.log(typeof d); //"undefined"
console.log(typeof e); //"undefined"
number
Il tipo di dato number è un numero appartenente all'insieme Z dei numeri interi relativi oppure un numero con la virgola. E' un dato primitivo ma può presentarsi anche come un oggetto. Il numero minimo e massimo che si possono esprimere in JavaScript si trovano stampando le costanti Number.MIN_VALUE e Number.MAX_VALUE. Esiste poi Infinity, un valore globale che è maggiore di qualunque altro numero, e -Infinity che è minore di qualunque altro. Essi sono il risultato di operazioni che darebbero un risultato maggiore / minore del massimo / minimo numero esprimibile. Infine esiste il valore globale NaN che si ottiene quando si cerca di fare un'operazione matematica non consentita, per esempio convertire la stringa "ciao" in un numero.
var f = 4;
var g = 7.459021;
var h = -30;
var i = Number.MAX_VALUE;
var j = -0; //esistono sia 0 che -0!
var k = Infinity;
var l = -Infinity;
var m = NaN;
console.log(typeof f); //"number"
console.log(typeof g); //"number"
console.log(typeof h); //"number"
console.log(typeof i); //"number"
console.log(typeof j); //"number"
console.log(typeof k); //"number"
console.log(typeof l); //"number"
console.log(typeof m); //"number"
string
Il tipo di dato string è uno o una serie di caratteri. Una stringa deve essere sempre delimitata da virgolette, singole o doppie. Può esistere anche una stringa vuota, cioè le virgolette non contengono nessun carattere. Anche in JavaScript è necessario fare l'escape dei caratteri come apostrofi e virgolette che devono essere mantenute all'interno della stringa.
var j = "ciao!";
var k = 'Buongiorno \n Good morning \n Bonjour';
var l = "";
var m = ' ';
console.log(typeof j); //"string"
console.log(typeof k); //"string"
console.log(typeof l); //"string"
console.log(typeof m); //"string"
boolean
Il tipo di dato boolean può assumere solo due valori: true e false.
var n = true;
console.log(typeof n); //"boolean"
null
Il tipo di dato null rappresenta l'assenza di valore come undefined ma deve essere assegnato esplicitamente. E' un tipo primitivo ma se usiamo l'operatore typeof otteniamo come risultato "object".
var o = null;
console.log(typeof o); //"object"
symbol
Questo tipo di dato è stato aggiunto con es6 e non l'ho mai usato ma è comunque un tipo primitivo.
var p = Symbol("a"); //attenzione, non usare la parola chiave new
console.log(typeof p); //"symbol"
Tutti gli altri tipi di dato vengono definiti non primitivi o oggetti. Ci sono moltissimi tipi di oggetti in JavaScript, ma i più utilizzati sono:
object
Un object è una associazione chiave - valore dove la chiave può essere solo una stringa mentre il valore può essere anche di altro tipo.
var r = {
nome: "Paolino",
cognome: "Paperino",
auto: 313
}; //object literal
console.log(typeof r); //"object"
array
Un array è una associazione chiave - valore dove la chiave può essere solo numerica mentre il valore può essere anche di altro tipo. Per sapere se una variabile è un arraynon possiamo usare l'operatore typeofperchè questo ritorna "object" anche per gli array
var s = [1, 'ciao', 9.36584, true]; //array literal
console.log(typeof s); //"object"
function
In JavaScript anche le funzioni sono oggetti ma usando l'operatore typeof otteniamo "function" perchè sono un tipo prticolare di oggetti in quanto callable.
var t = function(){
console.log("ciao");
}; //anche la funzione è un tipo di oggetto
function prova() {
console.log("ciao");
}; // altro modo di dichiarare una funzione
console.log(typeof t); //"function"
Alcuni oggetti devono essere creati espressamente come istanze di una certa classe utilizzando la parola chiave new, mentre per object e arraypossiamo scrivere direttamente l'oggetto, questo viene detto object literal.
Date
Per rappresentare una data utilizziamo un'istanza della classe Date.
var u = new Date(); //stampa la data ed ora corrente
var v = new Date(1982, 4, 19); //stampa il 19 maggio 1982
console.log(typeof u); //"object"
console.log(typeof v); //"object"
RegExp
Per rappresentare una regular expression (cioè una sequenza di simboli che identifica un insieme di stringhe) usiamo un'istanza della classe RegExp.
var w = new RegExp('^[0-9]+$'); //si può anche scrivere come var w = /^\[0-9]+$/;
console.log(typeof w); //"object"
Con es6 sono stati aggiunti questi nuovi tipi:
Set
Un set è un insieme di valori unici.
var x= new Set(); //i valori ripetuti non verranno inclusi nel Set
x.add(3);
x.add(5);
x.add("ciao");
x.add(3);
x.add(5);
x.add("ciao");
x.add(3);
x.add(5);
x.add("ciao");
console.log(typeof x); //"object"
Map
Un map è un insieme di chiave - valore dove sia la chiave che il valore possono essere di qualsiasi tipo.
var y= new Map();
y.set("stringa", "valore associato alla chiave stringa'");
y.set(5, "valore associato alla chiave numerica");
console.log(typeof y); //"object"
Promise
Una promise rappresenta un'azione che non è ancora stata completata ma che lo sarà in futuro sia con esito positivo che negativo.
var z = new Promise(function(resolve, reject) {
//logica della funzione
});
console.log(typeof z); //"object"
A volte, anzichè creare un oggetto di una determinata classe, utilizziamo direttamente la classe attraverso i suoi metodi statici, ad esempio:
Math
Usiamo la classe Math quando dobbiamo fare operazioni matematiche.
var aa = Math.max(367, -984);
console.log(typeof aa); //"number"
<!-- no html -->
/* no css */
var a; //dichiarazione senza assegnazione, a vale undefined
var b = undefined; //assegnazione esplicita
var c = {};
var d = c.nome; //la proprietà nome non esiste nell'oggetto c, d vale undefined
function test(param) {
//se il parametro non viene passato nel momento della chiamata della funzione questo vale undefined
}
var e = test(); //se il ritorno di una funzione non è specificato, questa ritorna undefined
console.log(typeof a); //"undefined"
console.log(typeof b); //"undefined"
console.log(typeof d); //"undefined"
console.log(typeof e); //"undefined"
var f = 4;
var g = 7.459021;
var h = -30;
var i = Number.MAX_VALUE;
console.log(typeof f); //"number"
console.log(typeof g); //"number"
console.log(typeof h); //"number"
console.log(typeof i); //"number"
var j = "ciao!";
var k = 'Buongiorno \n Good morning \n Bonjour';
var l = "";
var m = ' ';
console.log(typeof j); //"string"
console.log(typeof k); //"string"
console.log(typeof l); //"string"
console.log(typeof m); //"string"
var n = true;
console.log(typeof n); //"boolean"
var o = null;
console.log(typeof o); //"object"
var p = Symbol("a"); //attenzione, non usare la parola chiave new
console.log(typeof p); //"symbol"
var r = {
nome: "Paolino",
cognome: "Paperino",
auto: 313
}; //object literal
console.log(typeof r); //"object"
var s = [1, 'ciao', 9.36584, true]; //array literal
console.log(typeof s); //"object"
var t = function(){
console.log("ciao");
}; //anche la funzione è un tipo di oggetto
function prova() {
console.log("ciao");
}; // altro modo di dichiarare una funzione
console.log(typeof t); //"function"
var u = new Date(); //stampa la data ed ora corrente
var v = new Date(1982, 4, 19); //stampa il 19 maggio 1982
console.log(typeof u); //"object"
console.log(typeof v); //"object"
var w = new RegExp('^[0-9]+$'); //si può anche scrivere come var w = /^\[0-9]+$/;
console.log(typeof w); //"object"
var x= new Set(); //i valori ripetuti non verranno inclusi nel Set
x.add(3);
x.add(5);
x.add("ciao");
x.add(3);
x.add(5);
x.add("ciao");
x.add(3);
x.add(5);
x.add("ciao");
console.log(typeof x); //"object"
var y = new Map();
y.set("stringa", "valore associato alla chiave stringa");
y.set(5, "valore associato alla chiave numerica");
console.log(typeof y); //"object"
var z = new Promise(function(resolve, reject) {
//logica della funzione
});
console.log(typeof z); //"object"
var aa = Math.max(367, -984);
console.log(typeof aa); //"number"
Differenze tra i tipi primitivi e non
I tipi primitivi sono immutabili e vengono comparati per valore, i non primitivi sono mutabili e vengono comparati per riferimento. Si può rendere immutabile un tipo non primitivo utilizzando Object.freeze(obj)
var a = 1; //1 è un number, quindi un tipo primitivo
var b = a;
a = 2; //ora a vale 2 ma b resta invariato, a meno che non assegniamo a b un altro valore esplicitamente questo non può essere cambiato
console.log(a); //2
console.log(b); //1
var c = 3;
var d = 3;
if(c == d) { //stiamo confrontando i valori di c e d
console.log("c e d sono uguali"); //verrà stampata questa stringa
}
else {
console.log("c e d sono diversi");
}
var e = { //un oggetto non è un tipo primitivo
nome: "Paperina"
}
var f = e;
e.nome = "Minnie"; //ora abbiamo cambiato e, anche f cambierà di conseguenza
console.log(e);
console.log(f);
var g = {
nome: "Pippo"
}
var h = {
nome: "Pippo"
}
if(g == h) { //stiamo confrontando i puntamenti in memoria di g e h, non i loro valori
console.log("g e h sono uguali");
}
else {
console.log("g e h sono diversi"); //verrà stampata questa stringa
}
var i = {
nome: "Mickey",
cognome: "Mouse"
}
Object.freeze(i);
i.nome = "Topo"; //nessun effetto
i.lavoro = "Detective"; //nessun effetto
console.log(i); //{nome: "Mickey", cognome: "Mouse"}
var j = {
nome: "Mickey",
cognome: "Mouse",
amici: ["Pippo", "Basettoni"]
}
Object.freeze(j);
j.amici[1] = "commissario Basettoni"; //ha effetto perchè Object.freeze agisce solo sul primo livello del'oggetto
console.log(j); //{nome: "Mickey", cognome: "Mouse", amici: ["Pippo", "commissario Basettoni"]}
//Attenzione!!
var a = [1, 2];
var b = a;
a = []; //non sto modificando a ma sto riassegnando a
console.log(b); //1, 2
<!-- no html -->
/* no css */
var a = 1; //1 è un number, quindi un tipo primitivo
var b = a;
a = 2; //ora a vale 2 ma b resta invariato, a meno che non assegniamo a b un altro valore esplicitamente questo non può essere cambiato
console.log(a); //2
console.log(b); //1
var c = 3;
var d = 3;
if(c == d) { //stiamo confrontando i valori di c e d
console.log("c e d sono uguali"); //verrà stampata questa stringa
}
else {
console.log("c e d sono diversi");
}
var e = { //un oggetto non è un tipo primitivo
nome: "Paperina"
}
var f = e;
e.nome = "Minnie"; //ora abbiamo cambiato e, anche f cambierà di conseguenza
console.log(e);
console.log(f);
var g = {
nome: "Pippo"
}
var h = {
nome: "Pippo"
}
if(g == h) { //stiamo confrontando i puntamenti in memoria di g e h, non i loro valori
console.log("g e h sono uguali");
}
else {
console.log("g e h sono diversi"); //verrà stampata questa stringa
}
E' possibile wrappare i tipi primitivi boolean number e string nelle loro controparti oggetto ma non è di nessuna utilità perchè vengono comunque trattati come primitivi.
var a = new Boolean(true);
var b = new String("a");
var c = new Number(3);
console.log(typeof a); //object
console.log(typeof b); //object
console.log(typeof c); //object
console.log(a instanceof Boolean); //true
console.log(b instanceof String); //true
console.log(c instanceof Number); //true
var d = !a;
console.log(typeof d); //boolean
var e = b + "ciao";
console.log(typeof e); //string
var f = c + 5;
console.log(typeof f); //number