web-dev-qa-db-fra.com

Pourquoi instanceof renvoie false pour certains littéraux?

"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

Les littéraux de tableau et les littéraux d'objet correspondent ...

[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true

Pourquoi ne pas tous? Ou pourquoi ne font-ils pas tous pas?
Et de quoi s'agit-il alors?

C'est la même chose dans FF3, IE7, Opera et Chrome. Donc, au moins c'est cohérent.


Quelques manqués.

12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
268
Jonathan Lonowski

Les primitives sont d'un type différent des objets créés à partir de Javascript. À partir de la documentation de l'API 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)

Je ne trouve aucun moyen de construire des types primitifs avec du code, ce n'est peut-être pas possible. C'est probablement pourquoi les gens utilisent typeof "foo" === "string" au lieu de instanceof.

Un moyen facile de se souvenir de choses comme celle-ci est de se demander: "Je me demande ce qui serait sain et facile à apprendre"? Quelle que soit la réponse, Javascript fait l'autre chose.

385
John Millikin

J'utilise:

function isString(s) {
    return typeof(s) === 'string' || s instanceof String;
}

Parce qu'en JavaScript, les chaînes peuvent être des littéraux ou des objets.

93
axkibe

En JavaScript, tout est un objet (ou peut au moins être traité comme un objet), sauf primitives (booleans, null, numbers, strings et la valeur undefined (et le symbole dans 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

Comme vous pouvez le voir, les tableaux et la valeur null sont tous considérés comme des objets (null est une référence à un objet qui n'existe pas). Les fonctions sont distinguées car elles constituent un type spécial d'objets appelables . Cependant, ils sont toujours des objets.

D'autre part, les littéraux true, 0, "" Et undefined ne sont pas des objets. Ce sont des valeurs primitives en JavaScript. Cependant, les booléens, les nombres et les chaînes ont également les constructeurs Boolean, Number et String respectivement, qui encapsulent leurs primitives respectives pour offrir une fonctionnalité supplémentaire:

console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0));     // object
console.log(typeof new String(""));    // object

Comme vous pouvez le voir lorsque des valeurs primitives sont encapsulées dans les constructeurs Boolean, Number et String, elles deviennent respectivement des objets. L'opérateur instanceof ne fonctionne que pour les objets (c'est pourquoi il renvoie false pour les valeurs primitives):

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

Comme vous pouvez le constater, typeof et instanceof ne suffisent pas pour déterminer si une valeur est un booléen, un nombre ou une chaîne - typeof ne fonctionne que pour les booléens, les nombres et les chaînes primitifs. ; et instanceof ne fonctionne pas pour les booléens primitifs, les nombres et les chaînes.

Heureusement, il existe une solution simple à ce problème. L'implémentation par défaut de toString (c'est-à-dire telle qu'elle est définie de manière native sur Object.prototype.toString) Renvoie la propriété interne [[Class]] Des valeurs et des objets primitifs:

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 propriété interne [[Class]] D'une valeur est beaucoup plus utile que la typeof la valeur. Nous pouvons utiliser Object.prototype.toString Pour créer notre propre version (plus utile) de l'opérateur typeof comme suit:

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

J'espère que cet article a aidé. Pour en savoir plus sur les différences entre les primitives et les objets encapsulés, lisez le billet de blog suivant: La vie secrète des primitives JavaScript

56
Aadit M Shah

Vous pouvez utiliser la propriété constructeur:

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
31
user144049
 typeof(text) === 'string' || text instanceof String; 

vous pouvez l'utiliser, cela fonctionnera pour les deux cas

  1. var text="foo"; // typeof fonctionnera

  2. String text= new String("foo"); // instanceof fonctionnera

6
saurabhgoyal795

Je pense avoir mis au point une solution viable:

Object.getPrototypeOf('test') === String.prototype    //true
Object.getPrototypeOf(1) === String.prototype         //false
1
Robby Harris

Ceci est défini dans la spécification ECMAScript Section 7.3.19 Step : If Type(O) is not Object, return false.

En d'autres mots, si le Obj dans Obj instanceof Callable n'est pas un objet, le instanceof court-circuitera directement à false.

1
HKTonyLee