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?
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.
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).
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]';
}
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.
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)
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
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.
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.
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]"
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
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.
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
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é.
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
J'utilisais cette ligne de code:
if (variable.Push) {
// variable is array, since AMAIK only arrays have Push() method.
}
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);};
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]
De w3schools :
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
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.
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([]);
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) {}