有没有办法有效地检查变量是Object还是Array,在NodeJS& V8?
我正在为MongoDB和NodeJS编写一个模型,并且要遍历对象树,我需要知道对象是简单的(Number,String,...)还是复合(Hash,Array)。
V8似乎有快速内置Array.isArray
,但如何检查对象是否是对象?我的意思是复杂的对象,如哈希{}
或类的实例,而不是new String()
?
通常可以这样做:
Object.prototype.toString.call(object) == "[object Object]"
或者这个:
object === Object(object)
但似乎这种操作并不便宜,也许有一些效率更高?如果它不是通用的并且不适用于所有引擎,那就没关系,我只需要在V8上工作。
答案 0 :(得分:76)
只需检查对象或数组而无需额外的函数调用(速度)。
<强> 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
答案 1 :(得分:22)
所有对象都是ECMAScript中至少一个类的实例 - Object
。您只能使用Object#toString
区分内置类和普通对象的实例。它们都具有相同的复杂程度,例如,它们是使用{}
还是new
运算符创建的。
Object.prototype.toString.call(object)
是区分正常对象和其他内置类实例的最佳选择,因为object === Object(object)
在此处不起作用。但是,我看不出你为什么需要做你正在做的事情的原因,所以如果你分享用例,我可以提供更多的帮助。
答案 2 :(得分:19)
如果它只是检测你是否正在处理Object
,我能想到
Object.getPrototypeOf( obj ) === Object.prototype
但是,对于非对象原始值,这可能会失败。实际上,调用.toString()
来检索[[cclass]]属性并没有错。您甚至可以创建一个很好的语法,如
var type = Function.prototype.call.bind( Object.prototype.toString );
然后像
一样使用它if( type( obj ) === '[object Object]' ) { }
这可能不是最快的操作,但我不认为那里的性能泄漏太大。
答案 3 :(得分:14)
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]';
};
答案 4 :(得分:10)
我使用typeof
来确定我正在查看的变量是否是一个对象。如果是,那么我使用instanceof
来确定它是什么类型
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
答案 5 :(得分:9)
您好我知道这个主题已经过时但是有一种更好的方法来区分Node.js中的Array和任何其他对象看看docs。
var util = require('util');
util.isArray([]); // true
util.isArray({}); // false
var obj = {};
typeof obj === "Object" // true
答案 6 :(得分:3)
我可以使用我的项目的最佳方式。以棘手的方式使用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)
答案 7 :(得分:2)
刚刚找到了一个快速简单的解决方案来发现变量的类型。
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
修改强>
改善以防止&#39; undefined&#39;和&#39; null&#39;值:
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 :(得分:2)
如果您知道某个参数肯定是一个数组或一个对象,那么检查一个数组可能比检查具有类似内容的对象更容易。
function myIsArray (arr) {
return (arr.constructor === Array);
}
答案 9 :(得分:1)
在jQuery中查看他们所做的jQuery.isArray(...)
:
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]";
}
答案 10 :(得分:1)
我用这个函数来解决:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
答案 11 :(得分:0)
我知道它已经有一段时间了,但我想我会更新答案,因为有更新(更快更简单)的方法来解决这个问题。
由于ECMAscript 5.1哟可以使用isArray()
类中的Array
方法。
哟可以在MDN here中看到它的文档。
我认为您现在不应该遇到兼容性问题,但为了以防万一,如果您将此代码添加到代码中,那么Array.isArray()
是多层填充应始终是安全的:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
答案 12 :(得分:0)
仅供记录,lodash
也有isObject(value)