En JavaScript todo es un objeto (o al menos puede tratarse como un objeto), excepto las primitivas (booleanos, nulos, números, cadenas y el valor undefined(y símbolo en 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 puede ver, los objetos, las matrices y el valor nullse consideran objetos ( nulles una referencia a un objeto que no existe). Las funciones se distinguen porque son un tipo especial de objetos invocables . Sin embargo, siguen siendo objetos.
Por otro lado los literales true, 0, ""y undefinedno son objetos. Son valores primitivos en JavaScript. Sin embargo, los booleanos, los números y las cadenas también tienen constructores Boolean, Numbery Stringrespectivamente, que envuelven sus primitivas respectivas para proporcionar una funcionalidad adicional:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
Como puede ver cuando los valores primitivos se envuelven dentro de Boolean, Numbery los Stringconstructores, respectivamente, se convierten en objetos. El instanceofoperador solo funciona para objetos (por lo que devuelve falsevalores 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 puede ver ambos typeofy instanceofno son suficientes para probar si un valor es un valor booleano, un número o una cadena, typeofsolo funciona para booleanos, números y cadenas primitivos; y instanceofno funciona para booleanos, números y cadenas primitivos.
Afortunadamente, hay una solución simple para este problema. La implementación predeterminada de toString(es decir, como se define de forma nativa Object.prototype.toString) devuelve la [[Class]]propiedad interna de los valores y 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]
La [[Class]]propiedad interna de un valor es mucho más útil que typeofel valor. Podemos usar Object.prototype.toStringpara crear nuestra propia versión (más útil) del typeofoperador de la siguiente manera:
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 artículo haya ayudado. Para saber más sobre las diferencias entre los primitivos y los objetos envueltos, lea la siguiente publicación de blog: La vida secreta de los primitivos de JavaScript