javascript - array - ¿Por qué instanceof devuelve false para algunos literales?
javascript instanceof function (9)
Creo que he encontrado una solución viable:
Object.getPrototypeOf(''test'') === String.prototype //true
Object.getPrototypeOf(1) === String.prototype //false
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false
// the tests against Object really don''t make sense
Literales de matrices y literales de objetos ...
[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true
¿Por qué no todos ellos? O, ¿por qué no todos no ?
Y, ¿de qué son una instancia, entonces?
Es lo mismo en FF3, IE7, Opera y Chrome. Entonces, al menos es consistente.
Perdí algunos
12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
En JavaScript, todo es un objeto (o al menos puede tratarse como un objeto), excepto los primitives (booleanos, nulos, números, cadenas y el valor undefined
(y el 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 null
se consideran objetos ( null
es una referencia a un objeto que no existe). Las funciones se distinguen porque son un tipo especial de objetos que se pueden llamar . Sin embargo siguen siendo objetos.
Por otro lado, los literales true
, 0
, ""
y undefined
no son objetos. Son valores primitivos en JavaScript. Sin embargo, los valores booleanos, los números y las cadenas también tienen constructores Boolean
, Number
y String
respectivamente que envuelven sus respectivas primitivas para proporcionar 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 ajustan dentro de los constructores Boolean
, Number
y String
respectivamente, se convierten en objetos. El operador instanceof
solo funciona para objetos (por lo que devuelve false
para 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 puede ver, tanto typeof
como instanceof
no son suficientes para probar si un valor es un valor booleano, un número o una cadena - typeof
solo funciona para valores booleanos primitivos, números y cadenas; y instanceof
no funciona para booleanos primitivos, números y cadenas.
Afortunadamente hay una solución simple para este problema. La implementación predeterminada de toString
(es decir, como se define de forma nativa en Object.prototype.toString
) devuelve la propiedad interna [[Class]]
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 propiedad interna [[Class]]
de un valor es mucho más útil que el tipo del valor. Podemos usar Object.prototype.toString
para crear nuestra propia versión (más útil) del operador typeof
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 entrada del blog: La vida secreta de los primitivos de JavaScript
Los primitivos son un tipo de tipo diferente a los objetos creados desde Javascript. De la documentación de la API de Mozilla :
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
No encuentro ninguna forma de construir tipos primitivos con código, tal vez no sea posible. Probablemente esta sea la razón por la que la gente usa typeof "foo" === "string"
lugar de instanceof
.
Una forma fácil de recordar cosas como esta es preguntarse: "Me pregunto qué sería lo más sensato y fácil de aprender". Cualquiera que sea la respuesta, Javascript hace lo otro.
O simplemente puedes hacer tu propia función así:
function isInstanceOf(obj, clazz){
return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};
uso:
isInstanceOf('''',''String'');
isInstanceOf(new String(), ''String'');
Estos deben devolver ambos verdaderos.
Para mí la confusión causada por
"str".__proto__ // #1
=> String
Por lo tanto, "str" istanceof String
debería devolver true
porque la "istanceof" funciona de la siguiente manera:
"str".__proto__ == String.prototype // #2
=> true
Los resultados de la expresión # 1 y # 2 entran en conflicto entre sí, por lo que debe haber uno de ellos incorrecto.
# 1 está mal
Me doy cuenta de que la causa __proto__
no es una propiedad estándar, así que usa la estándar: Object.getPrototypeOf
Object.getPrototypeOf("str") // #3
=> TypeError: Object.getPrototypeOf called on non-object
Ahora no hay confusión entre la expresión # 2 y # 3
Puedes usar la propiedad del constructor:
''foo''.constructor == String // returns true
true.constructor == Boolean // returns true
Yo suelo:
function isString(s) {
return typeof(s) === ''string'' || s instanceof String;
}
Porque en JavaScript las cadenas pueden ser literales u objetos.
https://www.npmjs.com/package/typeof
Devuelve una representación de cadena de instanceof
(el nombre de los constructores)
function instanceOf(object) {
var type = typeof object
if (type === ''undefined'') {
return ''undefined''
}
if (object) {
type = object.constructor.name
} else if (type === ''object'') {
type = Object.prototype.toString.call(object).slice(8, -1)
}
return type.toLowerCase()
}
instanceOf(false) // "boolean"
instanceOf(new Promise(() => {})) // "promise"
instanceOf(null) // "null"
instanceOf(undefined) // "undefined"
instanceOf(1) // "number"
instanceOf(() => {}) // "function"
instanceOf([]) // "array"
typeof(text) === ''string'' || text instanceof String;
Puedes usar esto, funcionará tanto para el caso como para
var text="foo";
// typeof funcionaráString text= new String("foo");
// instanceof funcionará