web-dev-qa-db-de.com

Wie kann man effizient prüfen, ob die Variable ein Array oder ein Objekt ist (in NodeJS & V8)?

Gibt es eine Möglichkeit, in NodeJS & V8 effizient zu prüfen, ob die Variable Object oder Array ist? 

Ich schreibe ein Modell für MongoDB und NodeJS, und um den Objektbaum zu durchqueren, muss ich wissen, ob das Objekt einfach (Number, String, ...) oder zusammengesetzt (Hash, Array) ist.

Es scheint, dass in V8 schnell Array.isArray eingebaut ist, aber wie kann man prüfen, ob das Objekt ein Objekt ist? Ich meine komplexe Objekte wie hash {} oder Instanz der Klasse, nicht so etwas wie new String()?

Normalerweise kann es so gemacht werden:

Object.prototype.toString.call(object) == "[object Object]"

oder dieses:

object === Object(object)

Aber es scheint, dass diese Operationen nicht billig sind, vielleicht gibt es etwas effizienteres? Es ist in Ordnung, wenn es nicht universell ist und nicht bei allen Motoren funktioniert, ich brauche es nur, um an V8 zu arbeiten.

37

Alle Objekte sind Instanzen von mindestens einer Klasse - Object - in ECMAScript. Sie können nur mit Hilfe von Object#toString zwischen Instanzen eingebauter Klassen und normalen Objekten unterscheiden. Sie alle haben den gleichen Komplexitätsgrad, z. B. ob sie mit {} oder dem Operator new erstellt werden.

Object.prototype.toString.call(object) ist die beste Wahl, um zwischen normalen Objekten und Instanzen anderer integrierter Klassen zu unterscheiden, da object === Object(object) hier nicht funktioniert. Ich kann jedoch keinen Grund erkennen, warum Sie das tun müssen, was Sie tun. Wenn Sie also den Anwendungsfall teilen, kann ich Ihnen ein wenig mehr Hilfe anbieten.

20
Andy E

Zum einfachen Prüfen auf Object oder Array ohne zusätzlichen Funktionsaufruf (Geschwindigkeit).

isArray ()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isObject ()

isObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isObject(        )); // false
console.log(isObject(    null)); // false
console.log(isObject(    true)); // false
console.log(isObject(       1)); // false
console.log(isObject(   'str')); // false
console.log(isObject(      [])); // false
console.log(isObject(new Date)); // false
console.log(isObject(      {})); // true
71
zupa

Wenn es nur darum geht zu erkennen, ob Sie mit einer Object zu tun haben oder nicht, könnte ich daran denken

Object.getPrototypeOf( obj ) === Object.prototype

Dies würde jedoch wahrscheinlich für Nicht-Objekt-Grundwerte fehlschlagen. Tatsächlich ist es nicht falsch, .toString() aufzurufen, um die Eigenschaft [[cclass]] abzurufen. Sie können sogar eine Nice-Syntax erstellen

var type = Function.prototype.call.bind( Object.prototype.toString );

und benutze es dann gerne

if( type( obj ) === '[object Object]' ) { }

Es ist vielleicht nicht die schnellste Operation, aber ich denke nicht, dass das Leistungsleck dort zu groß ist.

18
jAndy

underscore.js verwendet Folgendes

toString = Object.prototype.toString;

_.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) == '[object Array]';
  };

_.isObject = function(obj) {
    return obj === Object(obj);
  };

_.isFunction = function(obj) {
    return toString.call(obj) == '[object Function]';
  };
14
Lordking

Ich benutze typeof, um festzustellen, ob die Variable, die ich betrachte, ein Objekt ist. Wenn ja, benutze ich instanceof, um festzustellen, um welche Art es sich handelt

var type = typeof elem;
if (type == "number") {
    // do stuff
}
else if (type == "string") {
    // do stuff
}
else if (type == "object") { // either array or object
    if (elem instanceof Buffer) {
    // other stuff
10
DanielS

Hallo, ich weiß, dieses Thema ist alt, aber es gibt eine viel bessere Möglichkeit, ein Array in Node.js von jedem anderen Objekt zu unterscheiden. Schauen Sie sich das docs an.

var util = require('util');

util.isArray([]); // true
util.isArray({}); // false

var obj = {};
typeof obj === "Object" // true
9
DeMeNteD

Am besten kann ich mein Projekt verwenden.Verwenden Sie hasOwnProperty auf knifflige Weise !.

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('Push') //true (This is an Array)

obj.constructor.prototype.hasOwnProperty('Push') // false (This is an Object)
2
VIJAY P

Ich habe diese Funktion verwendet, um zu lösen:

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

Ich habe gerade eine schnelle und einfache Lösung gefunden, um den Typ einer Variablen zu ermitteln.

ES6

export const isType = (type, val) => val.constructor.name.toLowerCase() === type.toLowerCase();

ES5 

function isType(type, val) {
  return val.constructor.name.toLowerCase() === type.toLowerCase();
}

Beispiele:

isType('array', [])
true
isType('array', {})
false
isType('string', '')
true
isType('string', 1)
false
isType('number', '')
false
isType('number', 1)
true
isType('boolean', 1)
false
isType('boolean', true)
true

EDIT

Verbesserung um 'undefined' und 'null' Werte zu verhindern:

ES6

export const isType = (type, val) => !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());

ES5 

function isType(type, val) {
  return !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());
}
1
jlcv

Wenn Sie wissen, dass ein Parameter definitiv entweder ein Array oder ein Objekt ist, ist es möglicherweise einfacher, nach einem Array zu suchen, als nach einem Objekt mit einem solchen Objekt.

function myIsArray (arr) {
    return (arr.constructor === Array);
}
1
weaVaer

wenn sie sich jQuery ansehen, tun sie dort jQuery.isArray(...):

    isArray = Array.isArray || function( obj ) {
    return jQuery.type(obj) === "array";
}

das führt uns zu: jQuery.type:

    type = function( obj ) {
    return obj == null ?
        String( obj ) :
        class2type[ toString.call(obj) ] || "object";
}

und wieder müssen wir schauen: class2type

class2type = {};

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

und in nativen JS:

var a, t = "Boolean Number String Function Array Date RegExp Object".split(" ");
for( a in t ) {
    class2type[ "[object " + t[a] + "]" ] = t[a].toLowerCase();
}

das endet mit:

var isArray = Array.isArray || function( obj ) {
    return toString.call(obj) === "[object Array]";
}
1
andlrc

ich habe eine einfache Funktion wie diese gefunden.

function getClass(object) {
    return Object.prototype.toString.call(object).slice(8, -1);
}

und Verwendung: 

if ( getClass( obj ) === 'String' ) {
    console.log( 'This is string' );
}
if ( getClass( obj ) === 'Array' ) {
    console.log( 'This is array' );
}
if ( getClass( obj ) === 'Object' ) {
    console.log( 'This is Object' );
}
0
l13s7 ae

Nur für den Datensatz hat lodash auch isObject (Wert)

0
Sash

Ich weiß, dass es eine Weile her ist, aber ich dachte, ich würde die Antwort aktualisieren, da es neue (schnellere und einfachere) Wege gibt, dieses Problem zu lösen ... Da ECMAscript 5.1 yo die isArray()-Methode in der Array verwenden kann Klasse.

Sie können die Dokumentation in MDN hier sehen.

Ich denke, Sie sollten heutzutage kein Kompatibilitätsproblem haben, aber für den Fall, wenn Sie dies in Ihren Code einfügen, sollten Sie immer sicher sein, dass Array.isArray() polyfilled ist:

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
0
Solano