How to efficiently check if variable is Array or Object (in NodeJS & V8)?

149,504

Solution 1

All objects are instances of at least one class – Object – in ECMAScript. You can only differentiate between instances of built-in classes and normal objects using Object#toString. They all have the same level of complexity, for instance, whether they are created using {} or the new operator.

Object.prototype.toString.call(object) is your best bet to differentiate between normal objects and instances of other built-in classes, as object === Object(object) doesn't work here. However, I can't see a reason why you would need to do what you're doing, so perhaps if you share the use case I can offer a little more help.

Solution 2

For simply checking against Object or Array without additional function call (speed).

isArray()

let 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()

let 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

Solution 3

If its just about detecting whether or not you're dealing with an Object, I could think of

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

However, this would probably fail for non-object primitive values. Actually there is nothing wrong with invoking .toString() to retreive the [[cclass]] property. You can even create a nice syntax like

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

and then use it like

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

It might not be the fastest operation but I don't think the performance leak there is too big.

Solution 4

underscore.js is using the following

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]';
  };

Solution 5

Hi I know this topic is old but there is a much better way to differentiate an Array in Node.js from any other Object have a look at the docs.

var util = require('util');

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

var obj = {};
typeof obj === "object" // true
Share:
149,504
Alex Craft
Author by

Alex Craft

I'm interested in Finance, Investing and Option Pricing. Building reliable, highly diversified and hedged portfolios. Analysing data, presenting it in a nice visual way. Turning idea into product quickly and efficiently. Tags: Asset Pricing, Kelly Criterion, Monte Carlo Modelling, Stochastic Processes, Mechanical and Statistical Hedging, Tail Hedging, Algorithms and Machine Learning, Trading.

Updated on July 05, 2022

Comments

  • Alex Craft
    Alex Craft almost 2 years

    Is there any way to efficiently check if the variable is Object or Array, in NodeJS & V8?

    I'm writing a Model for MongoDB and NodeJS, and to traverse the object tree I need to know if the object is simple (Number, String, ...) or composite (Hash, Array).

    It seems that V8 has fast built-in Array.isArray, but how to check if object is an Object? I mean complex object like hash {} or instance of class, not something like new String()?

    Usually it may be done as this:

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

    or this:

    object === Object(object)
    

    But it seems that this operations aren't cheap, maybe there's some more efficient? It's ok if it's not universal and doesn't works on all engines, I need it only to work on V8.