[英]How to efficiently check if variable is Array or Object (in NodeJS & V8)?
Is there any way to efficiently check if the variable is Object or Array, in NodeJS & V8?在 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).我正在为 MongoDB 和 NodeJS 编写模型,为了遍历对象树,我需要知道对象是简单的(数字、字符串……)还是复合的(哈希、数组)。
It seems that V8 has fast built-in Array.isArray
, but how to check if object is an Object?好像 V8 内置了快速的
Array.isArray
,但是如何检查 object 是否是 Object 呢? I mean complex object like hash {}
or instance of class, not something like new String()
?我的意思是像 hash
{}
这样的复杂对象或类的实例,而不是像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.
如果它不是通用的并且不适用于所有引擎,那没关系,我只需要它在 V8 上工作。
For simply checking against Object or Array without additional function call (speed).用于简单地检查对象或数组而无需额外的函数调用(速度)。
isArray() 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()
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
All objects are instances of at least one class – Object
– in ECMAScript.所有的对象都是至少一个类的实例-
Object
-在ECMAScript中。 You can only differentiate between instances of built-in classes and normal objects using Object#toString
.您只能使用
Object#toString
区分内置类和普通对象的实例。 They all have the same level of complexity, for instance, whether they are created using {}
or the new
operator.它们都具有相同的复杂程度,例如,无论它们是使用
{}
还是new
运算符创建的。
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. Object.prototype.toString.call(object)
是区分普通对象和其他内置类实例的最佳选择,因为object === Object(object)
在这里不起作用。 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.但是,我看不出为什么您需要做您正在做的事情,所以也许如果您分享用例,我可以提供更多帮助。
If its just about detecting whether or not you're dealing with an Object
, I could think of如果只是检测您是否正在处理
Object
,我可以想到
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.实际上,调用
.toString()
来检索 [[cclass]] 属性并没有错。 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.这可能不是最快的操作,但我不认为那里的性能泄漏太大。
underscore.js is using the following 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]';
};
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 .嗨,我知道这个话题很旧,但是有更好的方法可以将 Node.js 中的数组与任何其他对象区分开来,请查看文档。
var util = require('util');
util.isArray([]); // true
util.isArray({}); // false
var obj = {};
typeof obj === "Object" // true
I use typeof
to determine if the variable I'm looking at is an object.我使用
typeof
来确定我正在查看的变量是否是一个对象。 If it is then I use instanceof
to determine what kind it is如果是,那么我使用
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
Just found a quick and simple solution to discover type of a variable.刚刚找到了一个快速简单的解决方案来发现变量的类型。
ES6 ES6
export const isType = (type, val) => val.constructor.name.toLowerCase() === type.toLowerCase();
ES5 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 ES6
export const isType = (type, val) => !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());
ES5 ES5
function isType(type, val) {
return !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());
}
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);
}
The Best Way I Can Use My Project.Use hasOwnProperty
in Tricky Way!.我可以使用我的项目的最佳方式。以棘手的方式使用
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)
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.从ECMAscript 5.1 开始,您可以使用
Array
类中可用的isArray()
方法。
Yo can see it's documentation in MDN here .您可以在此处查看 MDN 中的文档。
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:我认为你现在不应该有兼容性问题,但以防万一,如果你将它添加到你的代码中,你应该始终确保
Array.isArray()
是多Array.isArray()
:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
looking at jQuery they in there jQuery.isArray(...)
they do:看看 jQuery 他们在那里
jQuery.isArray(...)
他们做:
isArray = Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
}
this leads us to: jQuery.type
:这导致我们:
jQuery.type
:
type = function( obj ) {
return obj == null ?
String( obj ) :
class2type[ toString.call(obj) ] || "object";
}
and again we have to look in: class2type
再次我们必须查看:
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:在原生 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]";
}
I've used this function to solve:我用这个函数解决了:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
Just for the record, lodash
also has isObject(value) 只是为了记录,
lodash
也有isObject(值)
Making - Object.isObject()制作 - Object.isObject()
Object.prototype.isObject = function (param) {
if(!param){return}
return param.constructor === Object ? true : false;
}
Calling - Object.isObject()调用 - Object.isObject()
Object.isObject({}) // returns true
Object.isObject([]) // returns false
Object.isObject("I am string") // returns false
If you're sure that the variable you're checking will be either an object or an array, you could use the length
property as well.如果您确定要检查的变量是对象或数组,则也可以使用
length
属性。
variable.length
on an array will return an integer between 1 and n whereas variable.length
on an object will return undefined
. variable.length
上的variable.length
将返回 1 和n之间的整数,而对象上的variable.length
将返回undefined
。
If you have other data types in the mix then you can add separate checks for those.如果混合中有其他数据类型,则可以为它们添加单独的检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.