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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8834126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:43:49  来源:igfitidea点击:

How to efficiently check if variable is Array or Object (in NodeJS & V8)?

javascriptnode.jsv8instanceoftypeof

提问by Alexey Petrushin

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? I mean complex object like hash {}or instance of class, not something like new String()?

好像 V8 内置了 fast Array.isArray,但是如何检查 object 是否是 Object 呢?我的意思是像散列{}或类的实例这样的复杂对象,而不是像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 上工作。

采纳答案by Andy E

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 newoperator.

所有对象都是至少一个类的实例Object——在 ECMAScript 中。您只能使用 区分内置类和普通对象的实例Object#toString。它们都具有相同的复杂程度,例如,无论它们是使用{}还是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. 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.

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

回答by zupa

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

回答by jAndy

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

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

回答by Lordking

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

回答by DanielS

I use typeofto determine if the variable I'm looking at is an object. If it is then I use instanceofto 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

回答by DeMeNteD

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

回答by weaVaer

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

回答by jlcv

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

回答by VIJAY P

The Best Way I Can Use My Project.Use hasOwnPropertyin 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)

回答by andlrc

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