¿Por qué instanceof devuelve false para algunos literales?
"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
Los literales de matriz y los literales de objeto coinciden...
[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 un ejemplo, entonces?
Es lo mismo en FF3, IE7, Opera y Chrome. Así que, al menos es consistente.
Se perdieron algunos.
12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
9 answers
Las primitivas son un tipo de tipo diferente a los objetos creados desde Javascript. Desde el Mozilla API docs :
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 puedo encontrar ninguna manera de construir tipos primitivos con código, tal vez no sea posible. Esta es probablemente la razón por la que la gente usa typeof "foo" === "string"
en lugar de instanceof
.
Una manera fácil de recordar cosas como esta es preguntarse "Me pregunto qué sería cuerdo y fácil de aprender"? Cualquiera que sea la respuesta, Javascript hace la otra cosa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 21:29:45
Utilizo:
function isString(s) {
return typeof(s) === 'string' || s instanceof String;
}
Porque en JavaScript las cadenas pueden ser literales u objetos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 20:41:26
En JavaScript todo es un objeto (o al menos puede ser tratado como un objeto), excepto primitivas (booleanos, null, 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 arrays y el valor null
son todos objetos considerados (null
es una referencia a un objeto que no existe). Las funciones se distinguen porque son un tipo especial de objetos llamables. Sin embargo, siguen siendo objetos.
Sobre la otro lado los literales true
, 0
, ""
y undefined
no son objetos. Son valores primitivos en JavaScript. Sin embargo, los 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 se puede ver cuando los valores primitivos se envuelven dentro de la Boolean
, Number
y String
constructores respectivamente se convierten en objetos. El operador instanceof
solo funciona para objetos (por eso 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
son insuficientes para probar si un valor es un booleano, un número o una cadena - typeof
solo funciona para booleanos primitivos, números y cadenas; y instanceof
no funciona para booleanos primitivos, números y cadenas.
Afortunadamente hay una solución simple a 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 ambos 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 typeof
el valor. Podemos usar Object.prototype.toString
para crear nuestra propia versión (más útil) del operador typeof
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 las primitivas y los objetos envueltos, lea la siguiente publicación del blog: La Vida Secreta de las primitivas de JavaScript
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-09 12:26:17
Puede usar la propiedad constructor:
'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-26 23:10:50
typeof(text) === 'string' || text instanceof String;
Puede usar esto, funcionará para ambos casos como
-
var text="foo";
// typeof funcionará -
String text= new String("foo");
// instanceof funcionará
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-23 11:30:06
Creo que he encontrado una solución viable:
Object.getPrototypeOf('test') === String.prototype //true
Object.getPrototypeOf(1) === String.prototype //false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-19 21:14:10
Https://www.npmjs.com/package/typeof
Devuelve una string-representation de instanceof
(el nombre del constructor)
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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-12 01:59:50
Para mí la confusión causada por
"str".__proto__ // #1
=> String
Así que "str" istanceof String
debería volver true
porque cómo funciona istanceof de la siguiente manera:
"str".__proto__ == String.prototype // #2
=> true
Resultados de la expresión #1 y #2 conflicto entre sí, por lo que debe haber uno de ellos mal.
#1 está mal
Me doy cuenta de que causado por el __proto__
es una propiedad no estándar, así que use 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-12 09:59:50
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');
Ambos deben devolver true.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-17 01:44:34