Comment vérifier si une variable est un tableau en JavaScript?

Je voudrais vérifier si une variable est soit un tableau, soit une valeur unique en JavaScript.

J'ai trouvé une solution possible …

if (variable.constructor == Array)... 

Est-ce la meilleure façon de le faire?

Il existe plusieurs façons de vérifier si une variable est un tableau ou non. La meilleure solution est celle que vous avez choisie.

 variable.constructor === Array 

C'est la méthode la plus rapide sur Chrome, et probablement tous les autres navigateurs. Tous les tableaux sont des objets, de sorte que vérifier la propriété du constructeur est un processus rapide pour les moteurs JavaScript.

Si vous rencontrez des problèmes pour savoir si une propriété d'objets est un tableau, vous devez d'abord vérifier si la propriété est là.

 variable.prop && variable.prop.constructor === Array 

D'autres façons sont les suivantes:

 variable instanceof Array 

Cette méthode utilise environ 1 / 3ème vitesse comme premier exemple. Encore assez solide, semble plus propre, si vous êtes tout à propos d'un code joli et pas tellement sur la performance. Mise à jour: instanceof Cela passe 2/3 la vitesse! Cependant, pour ceux qui veulent que ce soit un guichet unique, cela ne fonctionne pas avec les chiffres.

 Array.isArray(variable) 

Ce dernier est, à mon avis, le plus laid, et c'est le plus lent. En cours d'exécution environ 1/5, la vitesse est le premier exemple. Array.prototype, est en fait un tableau. Vous pouvez en savoir plus à ce sujet ici https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

Encore une autre mise à jour

 Object.prototype.toString.call(variable) === '[object Array]'; 

Ce type est le plus lent pour tenter de rechercher un tableau. Cependant, il s'agit d'un guichet unique pour tout type que vous recherchez. Cependant, puisque vous recherchez un tableau, utilisez simplement la méthode la plus rapide ci-dessus.

De plus, j'ai couru un test: http://jsperf.com/instanceof-array-vs-array-isarray/33 Alors, amusez-vous et vérifiez-le.

Remarque: @EscapeNetscape a créé un autre test car jsperf.com est en panne. http://jsben.ch/#/QgYAV Je voulais m'assurer que le lien original reste pour chaque fois que jsperf revient en ligne.

Vous pouvez également utiliser:

 if (value instanceof Array) { alert('value is Array!'); } else { alert('Not an array'); } 

Cela me semble une solution assez élégante, mais à chacun.

Modifier:

À partir de ES5, il y a maintenant:

 Array.isArray(value); 

Mais cela risque de se briser sur les navigateurs plus anciens, sauf si vous utilisez des polyfills (fondamentalement … IE8 ou similaire).

J'ai remarqué que quelqu'un a mentionné jQuery, mais je ne savais pas qu'il y avait une fonction isArray() . Il s'avère qu'il a été ajouté dans la version 1.3.

JQuery l'implique comme Peter suggère:

 isArray: function( obj ) { return toString.call(obj) === "[object Array]"; }, 

Ayant déjà mis beaucoup confiance dans jQuery (en particulier leurs techniques de compatibilité entre navigateurs), je procéderai soit à la version 1.3, mais aussi à leur fonction (à condition que la mise à niveau ne cause pas trop de problèmes) ou utilisez cette méthode suggérée directement dans mon code.

Merci beaucoup pour les suggestions.

Il existe de nombreuses solutions avec toutes leurs facettes. Cette page donne un bon aperçu. Une solution possible est:

 function isArray(o) { return Object.prototype.toString.call(o) === '[object Array]'; } 

C'est une question ancienne, mais ayant le même problème, j'ai trouvé une solution très élégante que je souhaite partager.

L'ajout d'un prototype à Array le rend très simple

 Array.prototype.isArray = true; 

Maintenant, une fois si vous avez un objet que vous voulez tester pour voir si c'est un tout, il vous suffit de vérifier la nouvelle propriété

 var box = doSomething(); if (box.isArray) { // do something } 

IsArray n'est disponible que s'il s'agit d'un tableau

Dans les navigateurs modernes (et certains navigateurs existants), vous pouvez le faire

 Array.isArray(obj) 

( Pris en charge par Chrome 5, Firefox 4.0, IE 9, Opera 10.5 et Safari 5)

Si vous devez prendre en charge les anciennes versions d'IE, vous pouvez utiliser es5-shim pour polyfill Array.isArray; Ou ajouter les éléments suivants

 # only implement if no native implementation is available if (typeof Array.isArray === 'undefined') { Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; } }; 

Si vous utilisez jQuery, vous pouvez utiliser jQuery.isArray(obj) ou $.isArray(obj) . Si vous utilisez le trait de soulignement, vous pouvez utiliser _.isArray(obj)

Si vous n'avez pas besoin de détecter des tableaux créés dans différents cadres, vous pouvez également utiliser une instanceof

 obj instanceof Array 

Remarque : le mot-clé des arguments qui peut être utilisé pour accéder à l'argument d'une fonction n'est pas une matrice, même si elle se comporte habituellement comme suit:

 var func = function() { console.log(arguments) // [1, 2, 3] console.log(arguments.length) // 3 console.log(Array.isArray(arguments)) // false !!! console.log(arguments.slice) // undefined (Array.prototype methods not available) console.log([3,4,5].slice) // function slice() { [native code] } } func(1, 2, 3) 

Via Crockford :

 function typeOf(value) { var s = typeof value; if (s === 'object') { if (value) { if (value instanceof Array) { s = 'array'; } } else { s = 'null'; } } return s; } 

Le principal défaut de Crockford mentionne une incapacité à déterminer correctement les tableaux qui ont été créés dans un autre contexte, par exemple, une window . Cette page a une version beaucoup plus sophistiquée si cela est insuffisant.

J'aime personnellement la suggestion de Peter: https://stackoverflow.com/a/767499/414784 (pour ECMAScript 3. Pour ECMAScript 5, utilisez Array.isArray() )

Les commentaires sur la publication indiquent, cependant, que si toString() est changé du tout, cette façon de vérifier un tableau échouera. Si vous voulez vraiment être spécifique et assurez-vous que toString() n'a pas été modifié et qu'il n'y a pas de problème avec l'attribut de classe d' [object Array] ( [object Array] est l'attribut de classe d'un objet qui est un tableau), je vous recommande de faire quelque chose comme ça:

 //see if toString returns proper class attributes of objects that are arrays //returns -1 if it fails test //returns true if it passes test and it's an array //returns false if it passes test and it's not an array function is_array(o) { // make sure an array has a class attribute of [object Array] var check_class = Object.prototype.toString.call([]); if(check_class === '[object Array]') { // test passed, now check return Object.prototype.toString.call(o) === '[object Array]'; } else { // may want to change return value to something more desirable return -1; } } 

Notez que dans JavaScript The Definitive Guide 6ème édition, 7.10, il dit que Array.isArray() est implémenté à l'aide d' Object.prototype.toString.call() dans ECMAScript 5. Notez également que si vous vous inquiétez de toString() ' La mise en œuvre de la mise en œuvre, vous devriez également vous soucier de toutes les autres modifications apportées à la méthode. Pourquoi utiliser push() ? Quelqu'un peut le changer! Une telle approche est stupide. Le contrôle ci-dessus est une solution offerte à ceux qui s'inquiètent de changer de toString() , mais je crois que la vérification n'est pas nécessaire.

Lorsque j'ai posté cette question, la version de JQuery que j'utilisais n'a pas inclus une fonction isArray . Si j'avais eu, je l'aurais certainement utilisé, j'espère que cette implémentation est la meilleure manière indépendante du navigateur pour effectuer cette vérification de type particulier.

Comme JQuery offre maintenant cette fonction, je l'utiliserais toujours …

 $.isArray(obj); 

(À partir de la version 1.6.2) Il est encore implémenté à l'aide de comparaisons sur des chaînes sous la forme

 toString.call(obj) === "[object Array]" 

J'ai pensé que j'ajouterais une autre option pour ceux qui pourraient déjà utiliser la bibliothèque Underscore.js dans leur script. Underscore.js a une fonction isArray () (voir http://underscorejs.org/#isArray ).

 _.isArray(object) 

Renvoie true si l'objet est une matrice.

Si vous n'utilisez que EcmaScript 5 et au-dessus, vous pouvez utiliser la fonction Array.isArray intégrée

par exemple,

 Array.isArray([]) // true Array.isArray("foo") // false Array.isArray({}) // false 

Dans Crockford's JavaScript The Good Parts , il existe une fonction pour vérifier si l'argument donné est un tableau:

 var is_array = function (value) { return value && typeof value === 'object' && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length')); }; 

Il explique:

Tout d'abord, nous demandons si la valeur est vérité. Nous faisons cela pour rejeter les valeurs nulles et autres fausses. Deuxièmement, nous demandons si le type de valeur est 'objet'. Cela sera vrai pour les objets, les tableaux et (bizarrement) null. Troisièmement, nous demandons si la valeur a une propriété de longueur qui est un nombre. Cela sera toujours vrai pour les tableaux, mais généralement pas pour les objets. Quatrièmement, nous demandons si la valeur contient une méthode d'épissure. Ceci sera de nouveau vrai pour tous les tableaux. Enfin, nous demandons si la propriété length est énumérable (la longueur sera-t-elle produite par un for en loop?). Ce sera faux pour tous les tableaux. C'est le test le plus fiable de la répartition que j'ai trouvé. Il est regrettable qu'il soit si compliqué.

Si vous utilisez Angular, vous pouvez utiliser la fonction angular.isArray ()

 var myArray = []; angular.isArray(myArray); // returns true var myObj = {}; angular.isArray(myObj); //returns false 

http://docs.angularjs.org/api/ng/function/angular.isArray

J'utilisais cette ligne de code:

 if (variable.push) { // variable is array, since AMAIK only arrays have push() method. } 

Code renvoyé par https://github.com/miksago/Evan.js/blob/master/src/evan.js

  var isArray = Array.isArray || function(obj) { return !!(obj && obj.concat && obj.unshift && !obj.callee);}; 

Pour ceux qui code-golf, un test peu fiable avec le moins de caractères:

 function isArray(a) { return a.map; } 

Ceci est couramment utilisé lors du déplacement / aplatissement d'une hiérarchie:

 function golf(a) { return a.map?[].concat.apply([],a.map(golf)):a; } input: [1,2,[3,4,[5],6],[7,[8,[9]]]] output: [1, 2, 3, 4, 5, 6, 7, 8, 9] 

La solution universelle est la suivante:

 Object.prototype.toString.call(obj)=='[object Array]' 

À partir de ECMAScript 5, une solution formelle est:

 Array.isArray(arr) 

En outre, pour les anciennes bibliothèques JavaScript, vous pouvez trouver ci-dessous la solution, même si elle n'est pas suffisamment précise:

 var is_array = function (value) { return value && typeof value === 'object' && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length')); }; 

Les solutions proviennent de http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript

De l' école maternelle :

 function isArray(myArray) { return myArray.constructor.toString().indexOf("Array") > -1; } 

J'ai aimé la réponse de Brian:

 function is_array(o){ // make sure an array has a class attribute of [object Array] var check_class = Object.prototype.toString.call([]); if(check_class === '[object Array]') { // test passed, now check return Object.prototype.toString.call(o) === '[object Array]'; } else{ // may want to change return value to something more desirable return -1; } } 

Mais vous pourriez faire comme ceci:

 return Object.prototype.toString.call(o) === Object.prototype.toString.call([]); 

J'ai créé ce petit code, qui peut renvoyer des types véritables.

Je ne suis pas encore sûr de la performance, mais c'est une tentative pour identifier correctement le type.

https://github.com/valtido/better-typeOf a également bloggé un peu à ce sujet ici http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/

Cela fonctionne, semblable au type actuel.

 var user = [1,2,3] typeOf(user); //[object Array] 

Il pense qu'il faudra peut-être un peu de réglage, et prendre en compte les choses, je n'ai pas rencontré ni testé correctement. De sorte que d'autres améliorations sont les bienvenues, qu'il s'agisse de performances judicieuses ou de reportage incorrect de typeOf.

Je pense utiliser myObj.constructor == Object et myArray.constructor == Array est la meilleure façon. Il est presque 20 fois plus rapide que l'utilisation de toString (). Si vous étendez des objets avec vos propres constructeurs et souhaitez que ces créations soient considérées comme des «objets», cela ne fonctionne pas, mais par ailleurs, c'est plus rapide. Typeof est tout aussi rapide que la méthode du constructeur, mais typeof [] == 'object' renvoie true qui sera souvent indésirable. http://jsperf.com/constructor-vs-tostring

Une chose à noter est que null.constructor lancera une erreur, donc si vous pouvez vérifier les valeurs nulles, vous devrez d'abord faire si (testThing! == null) {}

 function isArray(x){ return ((x != null) && (typeof x.push != "undefined")); } 

Étant donné que la propriété .length est spéciale pour les tableaux en javascript, vous pouvez simplement dire

 obj.length === +obj.length // true if obj is an array 

Underscorejs et plusieurs autres bibliothèques utilisent cette astuce courte et simple.

Quelque chose que je viens de combler:

if (item.length) //This is an array else //not an array