Javascript: identificare il tipo di un’oggetto

Spesso é necessario controllare se una variabile é di un certo tipo o di un’altro. Consideriamo questa funzione:

function media(a, b) {
    return (a + b) / 2;
}

Se anche solo uno dei due argomenti, a e b, non fosse un numero, si verificherebbe un errore.

isNaN

La funzione isNaN (is Not a Number, non é un numero) può essere utilizzata per capire se un oggetto sia un numero o meno.
Quindi, nel nostro esempio ossiamo evitare errori:

function media(a, b) {
    if (isNaN(a) || isNaN(b)) {
        return false;
    }
    return (a + b) / 2;
}

Tutto bene, quindi, per i numeri. E per altri oggetti?

L’operatore typeof

L’operatore typeof é usato per rilevare il tipo primitivo di una variabile (i principali sono booleano, stringa, numero, indefinito, funzione).
Ecco alcuni esempi:

typeof 5 === 'number' // vero
typeof 3.14 === 'number // vero
typeof 'stringa!' === 'string' // vero
typeof '' === 'string' // vero
typeof true === 'boolean' // vero
typeof function() {} === 'function' // vero
typeof Object.toString === 'function' // vero

Ci sono però alcune situazioi in cui questo operatore ha un comportamento inaspettato:

typeof ['a', 'b', 7] === 'object' // vero: infatti, array non e' un tipo primitivo - gli array sono instance dell'oggetto Array
typeof null === 'object' // vero: questa e' una stranezza di JavaScript, nata per motivi storici.

typeof new String('stringa!') === 'object' // vero: causa confusione - non usare queste forme!
typeof new Number(3.14) === 'object' // come sopra
typeof new Boolean(true) === 'object' // come sopra

L’operatore instanceof

In genere, il metodo migliore é l’operatore instanceof che, nella forma a instanceof b, ritorna true se a é instance di b, false altrimenti.

A = function() {}
B = function() {}

ogg = new A();

ogg instanceof A // vero
ogg instanceof B // falso, perche' B non e' nella catena prototipale di ogg
ogg instanceof Object // vero, poiche':
A.prototype instanceof Object // vero, quindi Object e' nella catena prototipale di ogg

Riprendendo gli ultimi esempi dell’operatore typeof:

['a', 'b', 7] instanceof Array // vero
new String('stringa!') instanceof String // vero
new Number(3.14) instanceof Number // vero
new Boolean(true) instanceof Boolean // vero

Purtroppo però neanche questo metodo é privo di ‘problemini’. Il più comune è che non funziona con Array provenienti da un’altro frame (ad es. da un’Iframe).
Quindi, come creare una funzione che possa affidabilmente controllare se un’oggetto é un’Array o meno?
Una soluzione sorprendentemente semplice é il metodo toString, che ci da il tipo dell’oggetto in forma di stringa:

function isArray(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
}