[英]How to efficiently check if variable is Array or Object (in NodeJS & V8)?
在 NodeJS 和 V8 中,有什么方法可以有效地检查变量是对象还是数组?
我正在为 MongoDB 和 NodeJS 编写模型,为了遍历对象树,我需要知道对象是简单的(数字、字符串……)还是复合的(哈希、数组)。
好像 V8 内置了快速的Array.isArray
,但是如何检查 object 是否是 Object 呢? 我的意思是像 hash {}
这样的复杂对象或类的实例,而不是像new String()
这样的东西?
通常可以这样做:
Object.prototype.toString.call(object) == "[object Object]"
或这个:
object === Object(object)
不过这个操作好像不便宜,说不定还有更高效的呢? 如果它不是通用的并且不适用于所有引擎,那没关系,我只需要它在 V8 上工作。
用于简单地检查对象或数组而无需额外的函数调用(速度)。
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
-在ECMAScript中。 您只能使用Object#toString
区分内置类和普通对象的实例。 它们都具有相同的复杂程度,例如,无论它们是使用{}
还是new
运算符创建的。
Object.prototype.toString.call(object)
是区分普通对象和其他内置类实例的最佳选择,因为object === Object(object)
在这里不起作用。 但是,我看不出为什么您需要做您正在做的事情,所以也许如果您分享用例,我可以提供更多帮助。
如果只是检测您是否正在处理Object
,我可以想到
Object.getPrototypeOf( obj ) === Object.prototype
但是,对于非对象原始值,这可能会失败。 实际上,调用.toString()
来检索 [[cclass]] 属性并没有错。 你甚至可以创建一个很好的语法,比如
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]';
};
嗨,我知道这个话题很旧,但是有更好的方法可以将 Node.js 中的数组与任何其他对象区分开来,请查看文档。
var util = require('util');
util.isArray([]); // true
util.isArray({}); // false
var obj = {};
typeof obj === "Object" // true
我使用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
刚刚找到了一个快速简单的解决方案来发现变量的类型。
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);
}
我可以使用我的项目的最佳方式。以棘手的方式使用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)
我知道已经有一段时间了,但我想我会更新答案,因为有新的(更快、更简单)的方法来解决这个问题。 从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]';
};
}
看看 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]";
}
我用这个函数解决了:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
只是为了记录, lodash
也有isObject(值)
制作 - Object.isObject()
Object.prototype.isObject = function (param) {
if(!param){return}
return param.constructor === Object ? true : false;
}
调用 - Object.isObject()
Object.isObject({}) // returns true
Object.isObject([]) // returns false
Object.isObject("I am string") // returns false
如果您确定要检查的变量是对象或数组,则也可以使用length
属性。
variable.length
上的variable.length
将返回 1 和n之间的整数,而对象上的variable.length
将返回undefined
。
如果混合中有其他数据类型,则可以为它们添加单独的检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.