2010-02-15 4 views
24

j'ai donc une fonction qui doit vérifier si un argument est un objet, mais cela échoue parce que:Comment vérifier si un objet n'est pas un tableau?

typeof [] // returns 'object' 

Ceci est un javascript classique Gotcha, mais je ne me souviens plus quoi faire pour accepter réellement des objets, mais pas de tableaux.

+2

dupliquer: http://stackoverflow.com/questions/1202841/what-is-the-best-way-to-check-if-an-object-is-an-array- ou-not-in-javascript –

Répondre

30

Essayez quelque chose comme ceci:

obj.constructor.toString().indexOf("Array") != -1 

ou (encore mieux)

obj instanceof Array 
+0

il semble que votre première suggestion soit la plus sûre et corrige également le problème indiqué par @Pointy ci-dessous. Merci :) – hojberg

+0

ou pour être plus précis: Object.prototype.toString.call (obj) === '[tableau d'objets]'; – hojberg

+1

jQuery a une méthode utilitaire 'isArray()'. http://api.jquery.com/jQuery.isArray/ @hojberg Je vous encourage à le faire.jQuery fait de même en interne. –

2

Avez-vous essayé ceci:

var test = []; 
if(test instanceof Array) { 
... 
} 

EDIT: Cette méthode ne fonctionne pas dans les environnements DOM multi-images (‘typeof’ considered useless - or how to write robust type checks). (Via Pointy)

+0

Pas vraiment une bonne solution. Voir http://juhukinners.com/2009/01/11/typeof-considered-useless-or-how-to-write-robust-type-checks/ – Pointy

+0

Bon point. Je ne le savais pas. –

17

Toutes ces réponses suggère que vous vérifiez pour voir (d'une manière ou d'une autre) si un objet est une instance de la classe « Array » (qui est, construit par « Array ») ne sont pas vraiment des solutions sûres. Ils fonctionneront parfois, peut-être la plupart du temps, mais tous les principaux cadres se sont éloignés de cette approche. L'un des principaux problèmes réside dans l'interaction entre plusieurs fenêtres (généralement une fenêtre parent et une ou plusieurs fenêtres frame ou iframe). Si vous transmettez un objet tableau créé dans une fenêtre dans une API résidant dans une autre fenêtre, tous ces tests échoueront. Pourquoi? Parce que ce que vous testez est de savoir si un objet est une instance de la classe "Array" dans votre contexte de fenêtre locale. En d'autres termes, lorsque vous faites référence à « Array » dans

if (myobject instanceof Array) { ... } 

ce que vous faites référence est window.Array, bien sûr. Eh bien, un tableau construit en une autre fenêtre est et non va être une instance de la classe Array dans votre fenêtre!

La vérification du nom du constructeur est probablement un peu plus sûr, même si c'est toujours risqué. À mon avis, il vaut mieux adopter une approche de typage du canard. C'est, au lieu de demander, "Est-ce un tableau?" demander à la place, "cet objet semble-t-il supporter un ensemble particulier d'API Array dont j'ai besoin dans cette circonstance?" Par exemple, "cet objet a-t-il une propriété length?" Javascript est une jolie langue "douce", et à peu près tout est modifiable. Ainsi, même si vous découvrez que quelque chose a été construit par "Array", vous ne savez toujours pas avec certitude ce que vous pouvez faire avec ou à ce sujet.

[modifier] Merci pour ce lien, @Lachlan - voici une description très claire des questions: http://juhukinners.com/2009/01/11/typeof-considered-useless-or-how-to-write-robust-type-checks/

+0

+1 pour une bonne explication. Merci pour le heads up –

3

Pour ce que ça vaut la peine, voici comment vérifie jQuery si quelque chose est un tableau:

isArray: function(arr) { 
    return !!arr && arr.constructor == Array; 
} 

Mais, this article recommande de le faire comme ceci:

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

Pour déterminer si un objet donné est un tableau, ECMAScript 5 introduit le Array.isArray() méthode, qui est actuellement pris en charge dans tous les navigateurs modernes. Reportez-vous à ce ECMAScript compatibility table.

Pour déterminer la classe d'un objet particulier, vous pouvez utiliser la méthode Object.prototype.toString().

Object.prototype.toString.call({}); // "[object Object]" 
 
Object.prototype.toString.call([]); // "[object Array]"

2

Les tableaux sont des objets en javascript après tout, tout ce que vous devez faire est de vérifier si le type de variable est un objet et dans le même temps, cet objet n'est pas instance de tableau classe.

var obj = {fname:'John',lname:'Doe'}; 

if(typeof obj === 'object' && !(obj instanceof Array)){ 
    return true ; 
} else { 
    return false; 
} 
+0

Bien que cela puisse être une réponse valable, vous êtes beaucoup plus susceptible d'aider les autres en leur expliquant ce que fait le code et comment cela fonctionne. Les réponses au code seulement ont tendance à recevoir moins d'attention positive et ne sont pas aussi utiles que les autres réponses. – Aurora0001

+1

@ Aurora0001 probablement vous avez raison, voici une description simple :) –

0

var obj = {first: 'Stack', last: 'Overflow'}; 
 
// var obj = ['Stack', 'overflow']; //You can uncomment this line and comment the above to check.. 
 

 
if(Object.prototype.toString.call(obj) !== '[object Array]') { 
 
    //your code.. 
 
    var str = ''; 
 
    for(var k in obj) { 
 
    \t str = str + obj[k] + ' '; 
 
    } 
 
    console.log('I love ', str); 
 
    alert('I love ' + str); 
 
} else { 
 
\t console.log('Could not process. Probably an array'); 
 
    alert('Could not process. Probably an array'); 
 
} 
 

 
console.log('Length is: ', Object.keys(obj).length); 
 
alert('Length is: ' + Object.keys(obj).length);

Laissez input être un Array ou un Object

Pour vérifier si un objet est un Array
if(Object.prototype.toString.call(input) === '[object Array]') {}

Pour vérifier si un objet est un Object
if(Object.prototype.toString.call(input) === '[object Object]') {}


S'il vous plaît noter Object.keys(input).length vous ramènera la longueur pour les deux Tableau et objet.

JS Fiddle example pour la même

2

Pour tester si quelque chose est une instance d'un tableau:

const arr = [1,2,3]; 
Array.isArray(arr); // true 

Pour tester est quelque chose est une instance d'un objet:

const obj = { 1: 'a', 2: 'b', 3: 'c' }; 
obj.constructor === Object; // true 

Note ce dernier jetterait une erreur si obj est null ou undefined, dans ce cas, vous pouvez utiliser: typeof obj === 'object' ou simplement faire une vérification nulle: obj && obj.constructor === Object.

1

s'il vous plaît utiliser Object.prototype.toString.call({}).slice(8,-1)==="Object" cela fonctionne pour tous les types de données, vous pouvez remplacer le paramètre à l'intérieur de la fonction d'appel et la comparaison aussi pour vérifier les différents types de données. cela fonctionne aussi pour le contrôle nul

Questions connexes