Em JavaScript, tudo é um objeto (ou pelo menos pode ser tratado como um objeto), exceto primitivas (booleanos, nulos, números, seqüências de caracteres e o valor undefined(e símbolo no 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
Como você pode ver objetos, matrizes e o valor nullsão todos considerados objetos ( nullé uma referência a um objeto que não existe). As funções são diferenciadas porque são um tipo especial de objetos que podem ser chamados . No entanto, eles ainda são objetos.
Por outro lado, os literais true, 0, ""e undefinednão são objetos. Eles são valores primitivos em JavaScript. No entanto, booleanos, números e seqüências de caracteres também têm construtores e Boolean, respectivamente, que agrupam suas respectivas primitivas para fornecer funcionalidade adicional:NumberString
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
Como você pode ver quando os valores primitivos são agrupados nos construtores Boolean, Numbere Stringrespectivamente eles se tornam objetos. O instanceofoperador trabalha apenas para objetos (é por isso que retorna falsepara valores primitivos):
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
Como você pode ver os dois typeofe instanceofé insuficiente para testar se um valor é um booleano, um número ou uma string - typeoffunciona apenas para booleanos primitivos, números e strings; e instanceofnão funciona para booleanos primitivos, números e seqüências de caracteres.
Felizmente, existe uma solução simples para esse problema. A implementação padrão de toString(ou seja, como é definida originalmente Object.prototype.toString) retorna a [[Class]]propriedade interna dos valores e objetos primitivos:
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]
A [[Class]]propriedade interna de um valor é muito mais útil que typeofo valor. Podemos usar Object.prototype.toStringpara criar nossa própria versão (mais útil) do typeofoperador da seguinte maneira:
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
Espero que este artigo tenha ajudado. Para saber mais sobre as diferenças entre objetos primitivos e agrupados, leia a seguinte postagem no blog: A Vida Secreta das Primitivas JavaScript