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

Ale*_*hin 42 javascript v8 typeof instanceof node.js

在NodeJS和V8中有没有办法有效地检查变量是Object还是Array?

我正在为MongoDB和NodeJS编写一个Model,并遍历对象树,我需要知道对象是简单的(Number,String,...)还是复合(Hash,Array).

似乎V8有快速内置Array.isArray,但如何检查对象是否是一个对象?我的意思是复杂的对象,如哈希{}或类的实例,不是这样的new String()

通常它可以这样做:

Object.prototype.toString.call(object) == "[object Object]"
Run Code Online (Sandbox Code Playgroud)

或这个:

object === Object(object)
Run Code Online (Sandbox Code Playgroud)

但似乎这种操作并不便宜,也许有一些效率更高?如果它不是通用的并且不适用于所有引擎,那就没关系,我只需要在V8上工作.

zup*_*upa 84

仅用于检查对象或数组而无需额外的函数调用(速度).

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
Run Code Online (Sandbox Code Playgroud)

则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
Run Code Online (Sandbox Code Playgroud)


And*_*y E 25

所有对象都是至少一个类的实例Object- 在ECMAScript中.您只能区分内置类和普通对象的实例Object#toString.它们都具有相同的复杂程度,例如,它们是使用{}还是new运算符创建的.

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

  • @AlexeyPetrushin:所以,大概有一些类实例传递给你的遍历函数的危险吗?值得注意的是,所有本机对象及其本机属性/方法都是不可枚举的,这意味着无论如何都无法遍历它们. (2认同)

jAn*_*ndy 20

如果它只是检测你是否正在处理一个Object,我能想到

Object.getPrototypeOf( obj ) === Object.prototype
Run Code Online (Sandbox Code Playgroud)

但是,对于非对象原始值,这可能会失败.实际上,调用.toString()[[cclass]]属性是没有错的.你甚至可以创建一个很好的语法

var type = Function.prototype.call.bind( Object.prototype.toString );
Run Code Online (Sandbox Code Playgroud)

然后像使用它一样

if( type( obj ) === '[object Object]' ) { }
Run Code Online (Sandbox Code Playgroud)

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

  • [它们非常快](http://jsperf.com/it-is-cheap),但仍然比`Array.isArray`慢10倍. (3认同)

Lor*_*ing 14

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]';
  };
Run Code Online (Sandbox Code Playgroud)

  • @Eloff:不,根据 ECMAScript 5 规范,如果你在已经是对象的东西上调用 `Object` 会发生这种情况:`结果是输入参数(没有转换)。` 这就是为什么它是 `===`到原始对象。所以它应该*非常*快。 (2认同)

Dan*_*elS 10

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
Run Code Online (Sandbox Code Playgroud)


DeM*_*teD 9

嗨,我知道这个主题已经过时但是有一种更好的方法来区分Node.js中的Array和任何其他对象看看文档.

var util = require('util');

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

var obj = {};
typeof obj === "Object" // true
Run Code Online (Sandbox Code Playgroud)


jlc*_*lcv 9

刚刚找到了一个快速简单的解决方案来发现变量的类型。

ES6

export const isType = (type, val) => val.constructor.name.toLowerCase() === type.toLowerCase();
Run Code Online (Sandbox Code Playgroud)

ES5

function isType(type, val) {
  return val.constructor.name.toLowerCase() === type.toLowerCase();
}
Run Code Online (Sandbox Code Playgroud)

例子:

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
Run Code Online (Sandbox Code Playgroud)

编辑

改进以防止“未定义”和“空”值:

ES6

export const isType = (type, val) => !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());
Run Code Online (Sandbox Code Playgroud)

ES5

function isType(type, val) {
  return !!(val.constructor && val.constructor.name.toLowerCase() === type.toLowerCase());
}
Run Code Online (Sandbox Code Playgroud)


wea*_*aer 7

如果您知道参数肯定是数组或对象,那么检查数组可能比检查具有类似内容的对象更容易。

function myIsArray (arr) {
    return (arr.constructor === Array);
}
Run Code Online (Sandbox Code Playgroud)