Как эффективно проверить, является ли переменная массивом или объектом (в NodeJS & V8)?
есть ли способ эффективно проверить, является ли переменная объектом или массивом в NodeJS & V8?
Я пишу модель для MongoDB и NodeJS, и чтобы пересечь дерево объектов, мне нужно знать, прост ли объект (номер, строка,...) или композитный (хэш, массив).
кажется, что V8 имеет быстрый встроенный Array.isArray
, но как проверить, является ли объект объектом? Я имею в виду сложный объект, такой как hash {}
или экземпляр класса, а не что-то вроде new String()
?
как правило, это может быть сделано, как это:
Object.prototype.toString.call(object) == "[object Object]"
или такой:
object === Object(object)
но кажется, что эти операции не дешевы, может быть, есть некоторые более эффективные? Это нормально, если он не универсален и не работает на всех двигателях, мне нужно только работать на V8.
14 ответов
все объекты являются экземплярами хотя бы одного класса – Object
– в ECMAScript. Вы можете различать только экземпляры встроенных классов и обычных объектов с помощью Object#toString
. Все они имеют одинаковый уровень сложности, например, создаются ли они с помощью {}
или new
оператора.
Object.prototype.toString.call(object)
лучше всего различать обычные объекты и экземпляры других встроенных классов, как object === Object(object)
здесь не работает. Однако я не вижу причины. почему вам нужно делать то, что вы делаете, поэтому, возможно, если вы поделитесь прецедентом, я могу предложить немного больше помощи.
для просто проверки против объекта или массива без дополнительного вызова функции (скорости).
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
, я мог бы подумать о
Object.getPrototypeOf( obj ) === Object.prototype
однако это, вероятно, не удастся для примитивных значений без объектов. На самом деле нет ничего плохого в вызове .toString()
для восстановления свойства [[cclass]]. Вы даже можете создать хороший синтаксис, такой как
var type = Function.prototype.call.bind( Object.prototype.toString );
и затем использовать его как
if( type( obj ) === '[object Object]' ) { }
Это может быть не самая быстрая операция, но я не думаю, что утечка есть тоже большой.
подчеркивания.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]';
};
Я использую 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
Привет я знаю, что эта тема старая, но есть гораздо лучший способ отличить массив в узел.js из любого другого объекта посмотрите на docs.
var util = require('util');
util.isArray([]); // true
util.isArray({}); // false
var obj = {};
typeof obj === "Object" // true
Лучший Способ Использовать Мой Проект.Использовать 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)
глядя на 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;
}
просто нашел быстрое и простое решение для обнаружения типа переменной.
ЕС6
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
редактировать
Improvment для предотвращения значений "undefined" и "null":
ЕС6
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);
}
Я нашел такую простую функцию.
function getClass(object) {
return Object.prototype.toString.call(object).slice(8, -1);
}
и использование :
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' );
}
Я знаю, что прошло некоторое время, но я думал, что обновлю ответ, так как есть новые (более быстрые и простые) способы решения этой проблемы.
С ECMAscript 5.1 вы можете использовать isArray()
метод доступен в Array
класса.
Yo может видеть, что это документация в MDN здесь.
Я думаю, что у вас не должно быть проблемы совместимости в настоящее время, но на всякий случай, если вы добавите это в свой код, вы всегда должны быть в безопасности, что Array.isArray()
is polyfilled:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}