NodeJS&V8で、変数がオブジェクトか配列かを効率的にチェックする方法はありますか?
MongoDBとNodeJSのモデルを作成しています。オブジェクトツリーをトラバースするには、オブジェクトが単純(Number、String、...)か、複合(Hash、Array)かを知る必要があります。
V8には高速な_Array.isArray
_が組み込まれているようですが、オブジェクトがオブジェクトであるかどうかを確認する方法はありますか? _new String()
のようなものではなく、ハッシュ_{}
_またはクラスのインスタンスのような複雑なオブジェクトを意味しますか?
通常、これは次のように実行できます。
_Object.prototype.toString.call(object) == "[object Object]"
_
またはこれ:
_object === Object(object)
_
しかし、この操作は安くはないようです。おそらくもっと効率的な方法があるのでしょうか?普遍的でなく、すべてのエンジンで機能しない場合でも問題ありません。V8でのみ機能する必要があります。
すべてのオブジェクトは、ECMAScriptの少なくとも1つのクラス(Object
)のインスタンスです。 _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
_
ただし、これはおそらく、オブジェクト以外のプリミティブ値では失敗します。実際、[[cclass]]プロパティを取得するために.toString()
を呼び出しても問題はありません。次のような素敵な構文を作成することもできます
_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]';
};
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
こんにちは、私はこのトピックが古いことを知っていますが、Node.jsの配列を他のオブジェクトと区別するはるかに良い方法があります docs を見てください。
var util = require('util');
util.isArray([]); // true
util.isArray({}); // false
var obj = {};
typeof obj === "Object" // true
変数の型を発見するための迅速で簡単な解決策を見つけました。
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
[〜#〜] edit [〜#〜]
「未定義」および「null」値を防止するための改善:
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)
そこにある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;
}
このような簡単な機能を見つけました。
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' );
}
レコードについては、lodash
にも isObject(value) があります
時間が経つことはわかっていますが、この問題を解決する新しい(より高速でシンプルな)方法があるため、答えを更新すると思いました。 ECMAscript 5.1 yoでは、Array
クラスで利用可能なisArray()
メソッドを使用できます。
YoのドキュメントはMDNで見ることができます こちら 。
現在、互換性の問題はないはずですが、念のため、これをコードに追加する場合は、Array.isArray()
がポリフィルされていることが常に安全である必要があります。
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}