web-dev-qa-db-fra.com

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

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

J'ai trouvé une solution possible ...

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

Est-ce la meilleure façon de procéder?

1685
Andy McCluggage

Il y a 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

Il s'agit de la méthode la plus rapide sur Chrome et probablement de tous les autres navigateurs. Tous les tableaux sont des objets. La vérification de la propriété constructeur est donc un processus rapide pour les moteurs JavaScript.

Si vous rencontrez des problèmes pour savoir si une propriété d'objet est un tableau, vous devez d'abord vérifier si la propriété s'y trouve.

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

Quelques autres moyens sont:

Array.isArray(variable)

Mettre à jour le 23 mai 2019 en utilisant Chrome 75, crier à @AnduAndrici pour m'avoir invité à revenir sur cette question avec sa question Ce dernier est , à mon avis le plus laid, et c’est l’un des plus le plus lent le plus rapide. Courir environ 1/5 de la vitesse comme le premier exemple. Ce gars est environ 2-5% plus lent, mais c'est assez difficile à dire. Solide à utiliser! Très impressionné par le résultat. Array.prototype, est en réalité un tableau. vous pouvez en savoir plus à ce sujet ici https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

variable instanceof Array

Cette méthode tourne autour 1/3 de la vitesse comme premier exemple. Toujours aussi solide, a l’air plus propre, si vous voulez du joli code et pas tellement de performance. Notez que la recherche de nombres ne fonctionne pas comme variable instanceof Number renvoie toujours false. Mise à jour: instanceof passe maintenant aux 2/3 de la vitesse!

Donc encore une autre mise à jour

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

Ce gars est le plus lent pour essayer de vérifier pour un tableau. Cependant, il s’agit d’un guichet unique pour tous les types que vous recherchez. Cependant, puisque vous recherchez un tableau, utilisez simplement la méthode la plus rapide ci-dessus.

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

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.

1592
jemiloii

Vous pouvez aussi utiliser:

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

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

Modifier:

À partir de ES5, il y a maintenant aussi:

Array.isArray(value);

Mais cela se répercutera sur les anciens navigateurs, sauf si vous utilisez des polyfill (en principe ... IE8 ou similaire).

1032
Brett Bender

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

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

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é à la version 1.3.

jQuery l'implémente comme Peter le suggère:

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

Ayant déjà beaucoup confiance en jQuery (en particulier leurs techniques de compatibilité entre navigateurs), je vais soit passer à la version 1.3 et utiliser sa fonction (à condition que la mise à niveau ne pose pas trop de problèmes) ou utiliser cette méthode suggérée directement dans ma code.

Merci beaucoup pour les suggestions.

77
Andy McCluggage

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

Array.isArray(obj)

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

Si vous avez besoin de supporter les anciennes versions d'IE, vous pouvez utiliser es5-shim pour polyfill Array.isArray; ou ajoutez ce qui suit

# 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 un trait de soulignement, vous pouvez utiliser _.isArray(obj)

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

obj instanceof Array

Remarque : le mot clé arguments pouvant être utilisé pour accéder à l'argument d'une fonction n'est pas un tableau, même s'il (généralement) se comporte comme un:

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)
66
Fela Winkelmolen

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

L'ajout d'un prototype à Array rend les choses très simples

Array.prototype.isArray = true;

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

var box = doSomething();

if (box.isArray) {
    // do something
}

isArray n'est disponible que si c'est un tableau

56
Ibu

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;
}

Crockford mentionne principalement l'incapacité de déterminer correctement les matrices créées dans un contexte différent, par exemple, window. Cette page a une version beaucoup plus sophistiquée si cela est insuffisant.

47
Hank Gay

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 le post indiquent cependant que si toString() est modifié, cette méthode de vérification d'un tableau échouera. Si vous voulez vraiment être spécifique et vous assurer que toString() n'a pas été modifié et que l'attribut de classe objects ne pose aucun problème ([object Array] est l'attribut de classe d'un objet qui est un tableau), Je 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 qu'en JavaScript, le Guide définitif - Édition définitive 7.1, indique que Array.isArray() est implémenté à l'aide de Object.prototype.toString.call() dans ECMAScript 5. Notez également que si vous souhaitez vous soucier de la modification de l'implémentation de toString(), vous devriez également vous soucier de toutes les autres méthodes intégrées qui changent aussi. Pourquoi utiliser Push()? Quelqu'un peut le changer! Une telle approche est stupide. La vérification ci-dessus est une solution offerte à ceux qui s’inquiètent de la modification de toString(), mais j’estime que cette vérification est inutile.

28
Brian

Lorsque j'ai posté cette question, la version de JQuery que j'utilisais n'incluait pas de fonction isArray. Si elle en avait eue, je l'aurais probablement utilisée, faisant confiance à cette implémentation pour constituer le meilleur moyen, indépendant du navigateur, d'effectuer cette vérification de type particulière.

Puisque JQuery offre maintenant cette fonction, je l’utiliserais toujours ...

$.isArray(obj);

(à partir de la version 1.6.2) Il est toujours implémenté en utilisant des comparaisons sur des chaînes de la forme

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

Si vous utilisez uniquement EcmaScript 5 et supérieur, vous pouvez utiliser la fonction intégrée Array.isArray

par exemple.,

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

J'ai pensé ajouter une autre option à ceux qui utilisent peut-être déjà 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 un tableau.

17
Benjen

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

11
joseph.l.hunsaker

Dans Crockford JavaScript The Good Parts , il y a 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:

Premièrement, nous demandons si la valeur est la vérité. Nous faisons cela pour rejeter les valeurs null et autres valeurs de fausseté. Deuxièmement, nous demandons si la valeur typeof est 'object'. Cela sera vrai pour les objets, les tableaux et (étrangement) 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. Ce sera à nouveau vrai pour tous les tableaux. Enfin, nous demandons si la propriété length est énumérable (la longueur sera-t-elle produite par une boucle for in?). Ce sera faux pour tous les tableaux. C’est le test le plus fiable que j’ai trouvé pour détecter la colère. Il est regrettable que ce soit si compliqué.

9
Yunzhou

La solution universelle est ci-dessous:

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

A partir de ECMAScript 5, une solution formelle est la suivante:

Array.isArray(arr)

En outre, pour les anciennes librairies JavaScript, vous pouvez trouver la solution ci-dessous bien qu'elle ne soit pas assez 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 viennent de http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript

5
PixelsTech

J'utilisais cette ligne de code:

if (variable.Push) {
   // variable is array, since AMAIK only arrays have Push() method.
}
4
Saeed Neamati

code référencé depuis 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);};
3
didxga

Pour ceux qui codent au golf, test peu fiable avec le moins de caractères:

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

Ceci est couramment utilisé pour traverser/aplatir 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]
2
Frambot

De w3schools :

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

J'ai créé ce petit morceau de code, qui peut renvoyer de vrais types.

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

https://github.com/valtido/better-typeOf a également blogué 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 que cela peut nécessiter un peu d'ajustement, et prendre en compte des choses, je ne l'ai pas vu ou testé correctement. ainsi, les améliorations ultérieures sont les bienvenues, qu’il s’agisse de performances optimales ou d’un ré-portage incorrect de typeOf.

1
Val

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 pouvez juste faire comme ça:

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

Je pense que l'utilisation de myObj.constructor == Object et de myArray.constructor == Array est la meilleure solution. Son presque 20 fois plus rapide que d'utiliser toString (). Si vous étendez des objets avec vos propres constructeurs et que vous voulez que ces créations soient considérées comme des "objets", cela ne fonctionnera pas, mais sinon, cela ira plus vite. typeof est aussi rapide que la méthode constructeur, mais typeof [] == 'objet' renvoie true, ce qui sera souvent indésirable. http://jsperf.com/constructor-vs-tostring

une chose à noter est que null.constructor va générer une erreur, donc si vous recherchez des valeurs NULL, vous devez le faire en premier si (testThing! == null) {}

1
user1585789