In JavaScript tutto è un oggetto (o almeno può essere trattato come un oggetto), tranne le primitive (booleane, null, numeri, stringhe e il valore undefined
(e il simbolo in ES6)):
console.log(typeof true); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof function () {}); // function
Come puoi vedere gli oggetti, le matrici e il valore null
sono tutti considerati oggetti ( null
è un riferimento a un oggetto che non esiste). Le funzioni si distinguono perché sono un tipo speciale di oggetti richiamabili . Tuttavia sono ancora oggetti.
D'altra parte i letterali true
, 0
, ""
e undefined
non sono oggetti. Sono valori primitivi in JavaScript. Tuttavia, i booleani, i numeri e le stringhe hanno anche dei costruttori e Boolean
, rispettivamente, che avvolgono le rispettive primitive per fornire funzionalità aggiuntive:Number
String
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
Come puoi vedere quando i valori primitivi sono racchiusi all'interno di Boolean
, Number
e String
rispettivamente i costruttori diventano oggetti. L' instanceof
operatore funziona solo per gli oggetti (motivo per cui restituisce false
valori primitivi):
console.log(true instanceof Boolean); // false
console.log(0 instanceof Number); // false
console.log("" instanceof String); // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number); // true
console.log(new String("") instanceof String); // true
Come puoi vedere entrambi typeof
e instanceof
non sono sufficienti per verificare se un valore è un valore booleano, un numero o una stringa - typeof
funziona solo per valori booleani, numeri e stringhe primitivi; e instanceof
non funziona con booleani, numeri e stringhe primitivi.
Fortunatamente esiste una soluzione semplice a questo problema. L'implementazione predefinita di toString
(ovvero come è nativamente definita Object.prototype.toString
) restituisce la [[Class]]
proprietà interna sia dei valori primitivi che degli oggetti:
function classOf(value) {
return Object.prototype.toString.call(value);
}
console.log(classOf(true)); // [object Boolean]
console.log(classOf(0)); // [object Number]
console.log(classOf("")); // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0))); // [object Number]
console.log(classOf(new String(""))); // [object String]
La [[Class]]
proprietà interna di un valore è molto più utile typeof
del valore. Possiamo usare Object.prototype.toString
per creare la nostra versione (più utile) typeof
dell'operatore come segue:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(typeOf(true)); // Boolean
console.log(typeOf(0)); // Number
console.log(typeOf("")); // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0))); // Number
console.log(typeOf(new String(""))); // String
Spero che questo articolo abbia aiutato. Per saperne di più sulle differenze tra primitivi e oggetti avvolti leggi il seguente post sul blog: The Secret Life of JavaScript Primitives