如何有效地检查variables是数组还是对象(在NodeJS&V8中)?

有没有什么办法来有效地检查NodeJS&V8中的variables是Object还是Array?

我正在为MongoDB和NodeJS编写Model,并且要遍历对象树,我需要知道对象是简单的(Number,String,…)还是复合(Hash,Array)。

看来,V8有快速内置的Array.isArray ,但如何检查对象是否是一个对象? 我的意思是像哈希{}或类的实例的复杂对象,而不是像new String()

通常可以这样做:

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

或这个:

 object === Object(object) 

但是这个行动似乎并不便宜,也许还有一些效率更高? 如果它不是通用的,并且不适用于所有引擎,那么我只需要在V8上工作。

所有的对象都是ECMAScript中的至less一个类 – Object实例。 您只能使用Object#toString区分内置类和普通对象的实例。 它们都具有相同的复杂程度,例如,它们是使用{}还是new操作符创build的。

Object.prototype.toString.call(object)是区分普通对象和其他内置类的实例的最佳select,因为object === Object(object)在这里不起作用。 但是,我不明白为什么你需要做你正在做的事情,所以也许如果你分享用例,我可以提供更多的帮助。

只需检查对象或数组,而无需额外的函数调用(速度)。

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 

如果它只是检测你是否正在处理一个Object ,我可以想到

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

但是,这可能会失败的非对象的原始值。 实际上调用.toString()来检索[[cclass]]属性是没有问题的。 你甚至可以创build一个很好的语法

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

然后像使用它

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

这可能不是最快的操作,但我不认为那里的性能泄漏太大了。

underscore.js正在使用以下内容

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

我使用typeof来确定我正在查看的variables是否是一个对象。 如果是的话,我使用instanceof来确定它是什么types的

 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 

嗨,我知道这个主题是旧的,但有一个更好的方法来区分Node.js中的数组与其他任何对象看看文档 。

 var util = require('util'); util.isArray([]); // true util.isArray({}); // false var obj = {}; typeof obj === "Object" // true 

我可以使用我的项目的最佳方式。使用hasOwnProperty在整蛊方式!

 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) 

看他们在那里jQuery.isArray(...)他们做的jQuery:

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

这导致我们: jQuery.type

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

再次,我们必须看看: 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(); }); 

和原生JS:

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

这结束了:

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

我用这个函数来解决:

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

刚刚find了一个快速而简单的解决scheme来发现variables的types。

ES6

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

ES5

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

例子:

 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 

编辑

改进以防止“未定义”和“空值”:

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()); } 

如果你知道一个参数肯定是一个数组或一个对象,那么检查一个数组可能会比使用类似这样的东西来检查一个对象更容易;

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

我发现这样简单的function。

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

和用法:

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

我知道这是一段时间,但我想我会更新答案,因为有新的(更快,更简单)的方法来解决这个问题。 由于ECMAscript 5.1可以使用Array类中可用的isArray()方法。

哟,在这里可以看到它在MDN的文档。

我认为你现在不应该有一个兼容性问题,但为了以防万一,如果你添加到你的代码,你应该总是安全Array.isArray()Array.isArray()

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