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.
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.
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
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.
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]';
};
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
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
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)
Ich habe diese Funktion verwendet, um zu lösen:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
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());
}
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);
}
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]";
}
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' );
}
Nur für den Datensatz hat lodash
auch isObject (Wert)
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]';
};
}