69 votes

Pourquoi 4 n'est pas une instance de Number ?

Simple curiosité :

  • 4 instanceof Number => false
  • new Number(4) instanceof Number => true ?

Pourquoi ? Même chose pour les cordes :

  • 'some string' instanceof String renvoie à faux
  • new String('some string') instanceof String => true
  • String('some string') instanceof String retourne également false
  • ('some string').toString instanceof String retourne également false

Pour les types objet, tableau ou fonction, l'opérateur instanceof fonctionne comme prévu. Je ne sais pas comment comprendre cela.

[ nouvelles perspectives ]

Object.prototype.is = function() {
        var test = arguments.length ? [].slice.call(arguments) : null
           ,self = this.constructor;
        return test ? !!(test.filter(function(a){return a === self}).length)
               : (this.constructor.name ||
                  (String(self).match ( /^function\s*([^\s(]+)/im )
                    || [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Newclass = function(){};  // anonymous Constructor function
var Some = function Some(){}; // named Constructor function
(5).is();                     //=> Number
'hello world'.is();           //=> String
(new Newclass()).is();        //=> ANONYMOUS_CONSTRUCTOR
(new Some()).is();            //=> Some
/[a-z]/.is();                 //=> RegExp
'5'.is(Number);               //=> false
'5'.is(String);               //=> true

0 votes

Vous devez utiliser Number.prototype.isPrototypeOf(inp) - votre façon de faire fonctionnerait aussi si elle était faite correctement : inp.constructor === Number ; elle pourrait échouer, car constructor est juste une propriété du prototype et peut être écrasé !

0 votes

Je ne suis pas sûr de comprendre ce que vous voulez dire par "peut être écrasé". Cela ne signifie pas que je peux écraser le constructeur avec un autre constructeur (j'ai essayé). D'ailleurs, Number.prototype.isPrototypeOf(4) renvoie false, donc je ne peux pas l'utiliser pour vérifier le type des valeurs primitives, n'est-ce pas ?

0 votes

C'était le but recherché (primitive !== primitive enveloppée) ! La vérification des constructeurs est dangereuse à cause de obj['constructor'] = ??? fonctionne ! Je vous suggère d'utiliser mon typeOf() pour traiter les primitives et les primitives enveloppées de la même manière, utilisez la fonction if(typeOf(x).toLowerCase() === 'string')

68voto

Christoph Points 64389

value instanceof Constructor est la même chose que Constructor.prototype.isPrototypeOf(value) et vérifient tous les deux la chaîne [[Prototype]]- de value pour les occurrences d'un objet spécifique.

Les chaînes de caractères et les nombres sont valeurs primitives Ils ne sont pas des objets et n'ont donc pas de [[Prototype]]. Ils ne fonctionneront donc que si vous les intégrez dans des objets normaux (ce que l'on appelle "boxing" en Java).

Aussi, comme vous l'avez remarqué, String(value) y new String(value) font des choses différentes : Si vous appelez les fonctions de construction des types intégrés sans utiliser l'attribut new ils essaient de convertir ('cast') l'argument au type spécifique. Si vous utilisez l'opérateur new ils créent un objet de type "wrapper".

new String(value) est à peu près équivalent à Object(String(value)) qui se comporte de la même manière que new Object(String(value)) .


Un peu plus sur les types en JavaScript : L'ECMA-262 définit les types primitifs suivants : Indéfini , Nulle , Booléen , Numéro y Chaîne de caractères . En outre, il existe le type Objet pour les choses qui ont des propriétés.

Par exemple, les fonctions sont de type Objet (ils ont simplement une propriété spéciale appelée [[Appel]]), et null est une valeur primitive de type Nulle . Cela signifie que le résultat de la typeof ne renvoie pas vraiment le type d'une valeur...

De plus, les objets JavaScript ont une autre propriété appelée [[Class]]. Vous pouvez l'obtenir via Object.prototype.toString.call(value) (ceci retournera '[objectClassname]' ). Les tableaux et les fonctions sont du type Objet mais leurs classes sont Array y Fonction .

Le test pour la classe d'un objet donné ci-dessus fonctionne lorsque instanceof échoue (par exemple, lorsque les objets sont transmis entre les limites de la fenêtre/image et ne partagent pas les mêmes prototypes).


Vous pouvez également consulter la version améliorée de l'application suivante typeof :

function typeOf(value) {
    var type = typeof value;

    switch(type) {
        case 'object':
        return value === null ? 'null' : Object.prototype.toString.call(value).
            match(/^\[object (.*)\]$/)[1]

        case 'function':
        return 'Function';

        default:
        return type;
    }
}

Pour les primitives, il retournera leur type en minuscule pour les objets, il renvoie leur classe en cas titre .

Exemples :

  • Pour les primitives de type Numéro (par exemple 5 ), il retournera 'number' pour les objets enveloppes de classe Numéro (par exemple new Number(5) ), il retournera 'Number' ;

  • Pour les fonctions, il renverra 'Function' .

Si vous ne voulez pas faire la distinction entre les valeurs primitives et les objets enveloppants (pour une raison quelconque, probablement mauvaise), utilisez typeOf(...).toLowerCase() .

Les bogues connus sont certaines fonctions intégrées dans IE, qui sont considérées comme étant 'Object' et une valeur de retour de 'unknown' lorsqu'il est utilisé avec certains objets COM+.

0 votes

@annakata : vérifiez ECMA-262 . les types s'appellent Undefined, Null, Boolean, Number, String et Object ; peu importe ce que l'on fait. typeof retourne...

0 votes

@Christoph - c'est très important puisque les objets wrapper sont en majuscules, et les typeofs en minuscules et rien d'autre n'est accessible. La convention et la pratique consistent donc à se référer aux types de données en minuscules, comme cela est précisé ici : developer.mozilla.org/Fr/JS/Glossaire

0 votes

@annakata : typeof est cassé - sa valeur de retour n'a rien à voir avec les types réels !

17voto

rkj Points 2478

Vous pouvez essayer d'évaluer :

>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"
>>> typeof(4)
"number"
>>> typeof(new Number(4))
"object"

3voto

meouw Points 21368

Comme indiqué dans la réponse de Christoph, les littéraux de chaîne et de nombre ne sont pas les mêmes que les objets Chaîne et Nombre. Si vous utilisez une des méthodes String ou Number sur le littéral, par exemple

'a string literal'.length

Le littéral est temporairement converti en objet, la méthode est invoquée et l'objet est éliminé.
Les littéraux présentent certains avantages distincts par rapport aux objets.

//false, two different objects with the same value
alert( new String('string') == new String('string') ); 

//true, identical literals
alert( 'string' == 'string' );

Utilisez toujours des littéraux pour éviter tout comportement inattendu !
Vous pouvez utiliser Number() et String() pour effectuer un typage si nécessaire :

//true
alert( Number('5') === 5 )

//false
alert( '5' === 5 )

1voto

AnthonyWJones Points 122520

Il s'agit d'une nuance de Javascript qui, à mon avis, permet à certains de s'en sortir. Le site instanceof de l'opérateur donnera toujours un résultat faux si le LHS n'est pas un object type.

Notez que new String('Hello World') ne donne pas lieu à un string mais est un object . Le site new donne toujours lieu à un objet. Je vois ce genre de choses :

function fnX(value)
{
     if (typeof value == 'string')
     {
          //Do stuff
     }
}
fnX(new String('Hello World'));

L'attente est que " Do Stuff " se produira mais ce n'est pas le cas car le type de la valeur est un objet.

1voto

Dans le cas des nombres primitifs, le isNaN pourrait également vous aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X