问题
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.
回答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.
回答2:
For simply checking against Object or Array without additional function call (speed).
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
回答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.
回答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]';
};
回答5:
I use typeof
to determine if the variable I'm looking at is an object. If it is then I use instanceof
to determine what kind it is
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
回答6:
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
回答7:
Just found a quick and simple solution to discover type of a 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();
}
Examples:
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
Improvment to prevent 'undefined' and 'null' values:
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());
}
回答8:
The Best Way I Can Use My Project.Use hasOwnProperty
in Tricky Way!.
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)
回答9:
If you know that a parameter will definitely be either an array or an object, it may be easier to check for an array compared to checking for an object with something like this.
function myIsArray (arr) {
return (arr.constructor === Array);
}
回答10:
looking at jQuery they in there jQuery.isArray(...)
they do:
isArray = Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
}
this leads us to: jQuery.type
:
type = function( obj ) {
return obj == null ?
String( obj ) :
class2type[ toString.call(obj) ] || "object";
}
and again we have to look in: 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();
});
and in native JS:
var a, t = "Boolean Number String Function Array Date RegExp Object".split(" ");
for( a in t ) {
class2type[ "[object " + t[a] + "]" ] = t[a].toLowerCase();
}
this ends up with:
var isArray = Array.isArray || function( obj ) {
return toString.call(obj) === "[object Array]";
}
回答11:
I've used this function to solve:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
回答12:
I know it's been a while, but I thought i would update the answer since there are new (faster and simpler) ways to solve this problem.
Since ECMAscript 5.1 yo can use the isArray()
method avaiable in the Array
class.
Yo can see it's documentation in MDN here.
I think you shouldn't have a compatibility problem nowadays, but just in case, if you add this to your code you should be always safe that Array.isArray()
is polyfilled:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
回答13:
Just for the record, lodash
also has isObject(value)
来源:https://stackoverflow.com/questions/8834126/how-to-efficiently-check-if-variable-is-array-or-object-in-nodejs-v8