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

时间:2022-02-14 20:01:31

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编写一个模型,要遍历对象树,我需要知道对象是简单(Number, String,…)还是组合(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()?

看起来V8拥有快速的内置数组。isArray,但是如何检查对象是否是对象?我是说像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上工作。

14 个解决方案

#1


18  

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.

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

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


60  

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

#3


18  

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

但是,对于非对象原语值,这可能会失败。实际上,调用. tostring()来重构[[cclass]]属性并没有什么错。您甚至可以创建一个很好的语法,比如

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


13  

underscore.js is using the following

下划线。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]';
  };

#5


10  

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

我使用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

#6


8  

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.

大家好,我知道这个话题已经过时了,但是有一种更好的方法来区分节点中的数组。任何其他对象的js都可以查看文档。

var util = require('util');

util.isArray([]); // true
util.isArray({}); // false

var obj = {};
typeof obj === "Object" // true

#7


2  

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)

#8


1  

looking at jQuery they in there jQuery.isArray(...) they do:

看看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

我们还要看一下class2类型

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

#9


1  

I've used this function to solve:

我用这个函数来解:

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

#10


1  

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

#11


1  

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

#12


0  

i found simple function like this.

我找到了这样一个简单的函数。

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

and usage :

和用法:

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

#13


0  

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 yo可以在数组类中使用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()是polyfill的:

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

#14


0  

Just for the record, lodash also has isObject(value)

为了记录,lodash也有isObject(value)

#1


18  

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.

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

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


60  

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

#3


18  

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

但是,对于非对象原语值,这可能会失败。实际上,调用. tostring()来重构[[cclass]]属性并没有什么错。您甚至可以创建一个很好的语法,比如

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


13  

underscore.js is using the following

下划线。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]';
  };

#5


10  

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

我使用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

#6


8  

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.

大家好,我知道这个话题已经过时了,但是有一种更好的方法来区分节点中的数组。任何其他对象的js都可以查看文档。

var util = require('util');

util.isArray([]); // true
util.isArray({}); // false

var obj = {};
typeof obj === "Object" // true

#7


2  

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)

#8


1  

looking at jQuery they in there jQuery.isArray(...) they do:

看看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

我们还要看一下class2类型

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

#9


1  

I've used this function to solve:

我用这个函数来解:

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

#10


1  

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

#11


1  

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

#12


0  

i found simple function like this.

我找到了这样一个简单的函数。

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

and usage :

和用法:

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

#13


0  

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 yo可以在数组类中使用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()是polyfill的:

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

#14


0  

Just for the record, lodash also has isObject(value)

为了记录,lodash也有isObject(value)