web-dev-qa-db-fra.com

Comment vérifier efficacement si variable est Array ou Object (dans NodeJS & V8)?

Existe-t-il un moyen de vérifier efficacement si la variable est Object ou Array, dans NodeJS & V8? 

J'écris un modèle pour MongoDB et NodeJS, et pour parcourir l'arbre des objets, j'ai besoin de savoir si l'objet est simple (Nombre, Chaîne, ...) ou composite (Hash, Array).

Il semble que V8 ait Array.isArray intégré rapide, mais comment vérifier si objet est un objet? Je veux dire un objet complexe comme hash {} ou une instance de classe, pas quelque chose comme new String()?

Habituellement, cela peut être fait comme ceci:

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

ou ca:

object === Object(object)

Mais il semble que ces opérations ne sont pas bon marché, il y en a peut-être plus efficaces? Ce n'est pas grave si ce n'est pas universel et ne fonctionne pas sur tous les moteurs, je n'ai besoin que de travailler sur V8.

37
Alexey Petrushin

Tous les objets sont des instances d'au moins une classe - Object - dans ECMAScript. Vous pouvez uniquement différencier les instances de classes intégrées des objets normaux à l'aide de Object#toString. Ils ont tous le même niveau de complexité, par exemple, qu’ils soient créés à l’aide de {} ou de l’opérateur new.

Object.prototype.toString.call(object) est votre meilleur choix pour différencier les objets normaux des instances d'autres classes intégrées, car object === Object(object) ne fonctionne pas ici. Cependant, je ne vois pas pourquoi vous auriez besoin de faire ce que vous faites. Par conséquent, si vous partagez le cas d'utilisation, je peux offrir un peu plus d'aide.

20
Andy E

Pour vérifier simplement avec Object ou Array sans appel de fonction supplémentaire (vitesse).

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

S'il s'agit simplement de détecter si vous avez ou non un Object, je pourrais penser à

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

Cependant, cela échouerait probablement pour les valeurs primitives non-objets. En fait, il n'y a rien de mal à invoquer .toString() pour retrouver la propriété [[cclass]]. Vous pouvez même créer une syntaxe de Nice comme

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

et ensuite l'utiliser comme

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

Ce n’est peut-être pas l’opération la plus rapide mais je ne pense pas que la perte de performance soit trop importante.

18
jAndy

underscore.js utilise ce qui suit

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

J'utilise typeof pour déterminer si la variable que je regarde est un objet. Si c’est le cas, j’utilise instanceof pour déterminer son type.

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

Bonjour, je sais que ce sujet est ancien, mais il existe un bien meilleur moyen de différencier un tableau dans Node.js de tout autre objet. Consultez la docs .

var util = require('util');

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

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

La meilleure façon d'utiliser mon projet.Utilisez hasOwnProperty de manière délicate !.

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

J'ai utilisé cette fonction pour résoudre:

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

Je viens de trouver une solution simple et rapide pour découvrir le type d'une variable.

ES6

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

ES5 

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

Exemples:

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

MODIFIER

Amélioration de la prévention des valeurs "non définies" et "nulles":

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

Si vous savez qu'un paramètre sera certainement soit un tableau, soit un objet, il peut être plus facile de rechercher un tableau plutôt que de rechercher un objet avec quelque chose comme ceci.

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

en regardant jQuery, ils y ont jQuery.isArray(...) ils le font:

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

cela nous amène à: jQuery.type:

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

et encore nous devons regarder dans: 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();
});

et en JS natif:

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

cela aboutit à:

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

j'ai trouvé une fonction simple comme celle-ci.

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

et utilisation: 

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

Pour mémoire, lodash a également isObject (valeur)

0
Sash