繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM