Meilleure façon d'obtenir le type d'une variable Javascript?

Est-il un meilleur moyen d'obtenir le type d'une variable en JS que typeof? Cela fonctionne bien quand vous le faites:

> typeof 1
"number"
> typeof "hello"
"string"

Mais c'est inutile quand vous essayez:

> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"

Je connais instanceof, mais cela vous oblige à connaître le type à l'avance.

> [1,2] instanceof Array
true
> r instanceof RegExp
true

Est-il un meilleur moyen?

224
demandé sur Ziki 2011-09-12 19:39:10

9 réponses

Angus Croll a récemment écrit un billet de blog intéressant à ce sujet -

Http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

Il passe en revue les avantages et les inconvénients des différentes méthodes puis définit une nouvelle méthode 'toType' -

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
192
répondu ipr101 2011-09-12 15:53:55

, Vous pouvez essayer d'utiliser constructor.name.

[].constructor.name
new RegExp().constructor.name

Comme avec tout JavaScript, quelqu'un finira invariablement par pointer que c'est en quelque sorte mauvais, alors Voici un lien vers une réponse qui couvre assez bien cela.

Une alternative consiste à utiliser Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)
44
répondu Alex Turpin 2017-05-23 12:26:23

Une fonction de capture de type raisonnablement bonne est celle utilisée par YUI3 :

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

Cela capture de nombreuses primitives fournies par javascript, mais vous pouvez toujours en ajouter d'autres en modifiant l'objet TYPES. Notez que typeof HTMLElementCollection dans Safari rapportera function, mais type (HTMLElementCollection) retournera object

38
répondu Nick Husher 2011-09-12 15:49:33

Vous pouvez trouver la fonction suivante utile:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

Ou dans ES7 (commentaire si d'autres améliorations)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

Résultats:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

Merci @johnrees pour m'avoir averti de: error, promise, generatorfunction

22
répondu Vix 2018-08-15 01:48:03

Aussi, nous pouvons changer un petit exemple de ipr101

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

Et appelez comme

"aaa".toType(); // 'string'
13
répondu greymaster 2012-11-08 13:52:33

Une ligne Fonction:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

Ce qui donne le même résultat que jQuery.type()

7
répondu Yukulélé 2017-05-01 11:50:28

, Vous pouvez appliquer Object.prototype.toString pour n'importe quel objet:

var toString = Object.prototype.toString;

console.log(toString.call([]));
//-> [object Array]

console.log(toString.call(/reg/g));
//-> [object RegExp]

console.log(toString.call({}));
//-> [object Object]

Cela fonctionne bien dans tous les navigateurs, à l'exception de IE - lorsque vous appelez ceci sur une variable obtenue à partir d'une autre fenêtre, il va simplement cracher [object Object].

3
répondu Andy E 2011-09-12 15:46:12

Mon 2¢! vraiment, une partie de la raison pour laquelle je jette ceci ici, malgré la longue liste de réponses, est de fournir un peu plus all in one tapez la solution et obtenez un feed back à l'avenir sur la façon de l'étendre pour en inclure plus real types.

Avec la solution suivante, comme mentionné ci-dessus, j'ai combiné quelques solutions trouvées ici, ainsi que d'incorporer un fix pour renvoyer une valeur de jQuery sur jQuery objet défini si disponible. J'ajoute également la méthode au prototype d'objet natif. Je sais que c'est souvent tabou, car cela pourrait interférer avec d'autres extensions, mais je laisse cela à user beware. Si vous n'aimez pas cette façon de le faire, copiez simplement la fonction de base où vous le souhaitez et remplacez toutes les variables de this par un paramètre d'argument à transmettre (comme les arguments[0]).

;(function() {  //  Object.realType
    function realType(toLower) {
        var r = typeof this;
        try {
            if (window.hasOwnProperty('jQuery') && this.constructor && this.constructor == jQuery) r = 'jQuery';
            else r = this.constructor && this.constructor.name ? this.constructor.name : Object.prototype.toString.call(this).slice(8, -1);
        }
        catch(e) { if (this['toString']) r = this.toString().slice(8, -1); }
        return !toLower ? r : r.toLowerCase();
    }
    Object['defineProperty'] && !Object.prototype.hasOwnProperty('realType')
        ? Object.defineProperty(Object.prototype, 'realType', { value: realType }) : Object.prototype['realType'] = realType;
})();

Ensuite, utilisez simplement avec facilité, comme ceci:

obj.realType()  //  would return 'Object'
obj.realType(true)  //  would return 'object'

Remarque: Il y a 1 argument praticables. Si est bool de true, alors le retour sera toujours en minuscules .

Plus D'Exemples:

true.realType();                            //  "Boolean"
var a = 4; a.realType();                    //  "Number"
$('div:first').realType();                   // "jQuery"
document.createElement('div').realType()    //  "HTMLDivElement"

Si vous avez quelque chose à ajouter qui peut être utile, comme définir quand un objet a été créé avec une autre bibliothèque (Moo, Proto,Yui, Dojo, etc...) n'hésitez pas à commenter ou à modifier ceci et à le garder plus précis et précis. Ou rouler sur le GitHub j'ai fait pour elle et laissez moi savoir. Vous y trouverez également un lien rapide vers un fichier cdn min.

3
répondu SpYk3HH 2016-07-09 16:38:22
function getType(obj) {
    if(obj && obj.constructor && obj.constructor.name) {
        return obj.constructor.name;
    }
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

Dans mes tests préliminaires, cela fonctionne plutôt bien. Le premier cas imprimera le nom de tout objet créé avec "new", et le 2ème cas devrait attraper tout le reste.

J'utilise (8, -1) parce que je suppose que le résultat va toujours commencer par [object et se terminer par ] mais je ne suis pas certain que ce soit vrai dans tous les scénarios.

2
répondu mpen 2016-06-06 16:10:07