Wie können wir in Javascript feststellen, ob ein Objekt ein Hash oder ein Array ist?

76

Die Ausgabe meines JSON-Aufrufs kann entweder ein Array oder ein Hash sein. Wie unterscheide ich zwischen diesen beiden?

Akshat
quelle

Antworten:

124

Moderne Browser unterstützen die Array.isArray(obj)Methode.

Siehe MDN für Dokumentation und eine Polyfüllung.

= ursprüngliche Antwort von 2008 =

Sie können die constuctor-Eigenschaft Ihrer Ausgabe verwenden:

if(output.constructor == Array){
}
else if(output.constructor == Object){
}
pawel
quelle
2
Dies kann zu Konflikten zwischen verschiedenen Seiten führen, da beide unterschiedliche Instanzen der Arrayund ObjectKonstruktorfunktionen haben, die nicht gleich sind. Ich bin mir nicht ganz sicher, wie ich ein Beispiel erstellen soll, das dies demonstriert, aber ich habe es irgendwo gelesen.
Ripper234
1
@ ripper234 Das Problem wird sich in einer Multi- windowUmgebung manifestieren .
Alex
3
+1 für die Metionierung von Array.isArray. Überprüfen Sie diesen Link für die Unterstützung von Kreditnehmern: kangax.github.io/compat-table/es5/#Array.isArray
SKuijers
1
Jeder, der underscore.js verwendet, könnte isArray und isObject nützlich finden.
Akotian
1
@akotian _.isObject gibt leider sowohl für Array als auch für Hash true zurück. Sie benötigen zusätzliche bedingte Logik, um eine Lösung mit Unterstrich auszubügeln.
Con Antonakos
31

Ist Objekt:

function isObject ( obj ) {
   return obj && (typeof obj  === "object");
}

Ist Array:

function isArray ( obj ) { 
  return isObject(obj) && (obj instanceof Array);
}

Da Arrays Objekte sind, möchten Sie zunächst testen, ob eine Variable ein Array ist und dann, ob es sich um ein Objekt handelt:

if (isArray(myObject)) {
   // do stuff for arrays
}
else if (isObject(myObject)) {
   // do stuff for objects
}
Borgar
quelle
1
Gute Antwort. Möglicherweise möchten Sie hinzufügen, dass jedes js-Objekt als Hash behandelt werden kann.
Rontologe
isObject (new Date ())) ist wahr, aber ein Datum ist kein Objekt / Hash im Sinne dieser Frage. Natürlich wenden wir es nur auf JSON an, aber der Methodenname ist dann wirklich verwirrend.
Schirrmacher
isObject
Gibt
9

Meinten Sie "Objekt" anstelle von "Hash"?

>>> var a = [];
>>> var o = {};
>>> a instanceof Array
true
>>> o instanceof Array
false
Jonny Buchanan
quelle
5

Ich habe eine Funktion erstellt, um festzustellen, ob es sich um ein Wörterbuch handelt.

exports.is_dictionary = function (obj) {
    if(!obj) return false;
    if(Array.isArray(obj)) return false;
    if(obj.constructor != Object) return false;
    return true;
};

// return true
test.equal(nsa_utils.is_dictionary({}), true);
test.equal(nsa_utils.is_dictionary({abc:123, def:456}), true);

// returns false
test.equal(nsa_utils.is_dictionary([]), false);
test.equal(nsa_utils.is_dictionary([123, 456]), false);
test.equal(nsa_utils.is_dictionary(null), false);
test.equal(nsa_utils.is_dictionary(NaN), false);
test.equal(nsa_utils.is_dictionary('hello'), false);
test.equal(nsa_utils.is_dictionary(0), false);
test.equal(nsa_utils.is_dictionary(123), false);
neoneye
quelle
Danke dafür. Es hat für die oben genannten Fälle funktioniert. Ich muss noch auf einen Fall stoßen, in dem Ihre Methode fehlschlägt.
Nav
1
if(Array.isArray(obj)) return false;<- Ist dies nicht redundant, da ein Array die nächste Prüfung ohnehin nicht besteht ( if(obj.constructor != Object))?
assert.equal(is_dictionary(new (class MyClass {})), true);schlägt fehl - die Instanz von MyClass ist definitiv ein Hash / Wörterbuch.
Angelos Pikoulas
Es wurde ein bisschen verbessert:const assert = require('assert'); const is_dictionary = function (obj) { if(!obj) return false; if(Array.isArray(obj)) return false; if (({}).toString.apply(obj) !== '[object Object]') return false; return true; }; // returns true along your own with these values new (class MyClass {}) Object.create({}) Object.create(null) // returns false along with yours new String('foo') new Number(123) ()=> {} function() {} new Map
Angelos Pikoulas
1

Überprüfen Sie das Objekt auf die Eigenschaft "Konstruktor". Es ist Array - es ist ein Array-Objekt.

var a = {
 'b': {Länge: 0},
 'c': [1,2]
}}

if (acconstructor == Array)
   für (var i = 0; i <Länge; i ++)
      alert (ac [i]);
sonst
   für (var s in ab);
      alert (ab [s]);

Sergey Ilinsky
quelle
0

Zum Parsen könnte sich json als nützlich erweisen :)

isArrayHashs = (attr) ->
  !!attr && attr.constructor == Array && isHash(attr[0])

isHash = (attr) ->
  !!attr && !$.isNumeric(attr) && attr.constructor == Object

attr [0] .constructor muss sein:

  • String
  • Numerisch
  • Array
  • Objekt
  • Nicht definiert
Vitya Ivliiev
quelle
0

Ein praktischerer und präziserer Begriff als Objekt, Hash oder Wörterbuch kann ein assoziatives Array sein . Objekt könnte auf viele unerwünschte Ereignisse zutreffen, z . B. typeof null === 'object'oder [1,2,3] instanceof Object. Die folgenden zwei Funktionen funktionieren seit ES3 und sind natürlich exklusiv.

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

console.assert(true === is_array([]));
console.assert(true === is_array([1,2,3]));
console.assert(true === is_array(new Array));
console.assert(true === is_array(Array(1,2,3)));

console.assert(false === is_array({a:1, b:2}));
console.assert(false === is_array(42));
console.assert(false === is_array("etc"));
console.assert(false === is_array(null));
console.assert(false === is_array(undefined));
console.assert(false === is_array(true));
console.assert(false === is_array(function () {}));
function is_associative_array(z) {
    return Object.prototype.toString.call(z) === '[object Object]';
}

console.assert(true === is_associative_array({a:1, b:2}));
console.assert(true === is_associative_array(new function Legacy_Class(){}));
console.assert(true === is_associative_array(new class ES2015_Class{}));

console.assert(false === is_associative_array(window));
console.assert(false === is_associative_array(new Date()));
console.assert(false === is_associative_array([]));
console.assert(false === is_associative_array([1,2,3]));
console.assert(false === is_associative_array(Array(1,2,3)));
console.assert(false === is_associative_array(42));
console.assert(false === is_associative_array("etc"));
console.assert(false === is_associative_array(null));
console.assert(false === is_associative_array(undefined));
console.assert(false === is_associative_array(true));
console.assert(false === is_associative_array(function () {}));

Beachten Sie, wie die Instanz einer Klasse als assoziatives Array behandelt wird. (Aber nicht die Instanz einer integrierten Klasse wie Date.)

Dank der Lösung von RobG in dieser Richtung für eine Array.isArray () -Polyfill. Dadurch wird auf die native toString () -Methode der Object-Klasse zugegriffen, mit der der Typ knapp und effizient gemeldet wird.

Bob Stein
quelle