JavaScriptで変数が配列なのか単一値なのかをチェックしたいのですが。
私は可能な解決策を見つけました...
if (variable.constructor == Array)...
これが最善の方法ですか。
変数が配列かどうかを調べる方法はいくつかあります。最善の解決策はあなたが選んだものです。
variable.constructor === Array
これはChrome上で最速の方法で、おそらく他のすべてのブラウザです。すべての配列はオブジェクトなので、コンストラクタプロパティをチェックすることはJavaScriptエンジンのための速いプロセスです。
オブジェクトのプロパティが配列かどうかを調べるのに問題がある場合は、まずそのプロパティがそこにあるかどうかを確認する必要があります。
variable.prop && variable.prop.constructor === Array
他にもいくつかあります。
variable instanceof Array
このメソッドは約実行されます 1/3スピード 最初の例として。それでも、かなりしっかりしていて、きれいなコードになっていて、パフォーマンスがそれほど重要ではない場合は、きれいに見えます。 variable instanceof Number
は常にfalse
を返すので、数字のチェックは機能しません。 更新:instanceof
は2/3のスピードになりました!
Array.isArray(variable)
この最後のものは、私の意見では、最も醜いものであり、そしてそれは最も遅いものの1つです。最初の例として約1/5の速度で実行します。 Array.prototypeは、実際には配列です。あなたはそれについての詳細をここで読むことができます https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
まだ別のアップデート
Object.prototype.toString.call(variable) === '[object Array]';
この男は配列をチェックしようとするのが最も遅いです。しかし、これはあなたが探しているすべてのタイプのためのワンストップショップです。ただし、配列を探しているので、上記の最も速い方法を使用してください。
また、私はいくつかのテストを実行しました: http://jsperf.com/instanceof-array-vs-array-isarray/33 だからいくつかの楽しみを持ってそれをチェックしてください。
注:jsperf.comが停止しているため、@ EscapeNetscapeは別のテストを作成しました。 http://jsben.ch/#/QgYAV jsperfがオンラインに戻ったときはいつでも元のリンクが残るようにしたかった。
あなたも使用することができます:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
これは私にとってはかなりエレガントな解決策のように思えますが、それぞれ独自のものです。
編集する
ES5の時点でもあります:
Array.isArray(value);
しかし、これは、あなたがポリフィルを使っているのでなければ、古いブラウザではうまくいきません(基本的にはIE8かそれに類似したものです)。
誰かがjQueryに言及しているのに気づきましたが、 isArray()
関数があることを知りませんでした。それはバージョン1.3で追加されたことがわかりました。
peterが提案しているように、jQueryはそれを実装します。
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
すでにjQueryに多くの信頼を置いているので(特にクロスブラウザ互換性のためのそれらのテクニック)、バージョン1.3にアップグレードしてその機能を使う(アップグレードがあまりにも多くの問題を引き起こさないという条件で)コード。
提案をどうもありがとう。
すべて独自の風変わりな解決策が複数あります。 このページ は良い概観を与えます。考えられる解決策の1つは次のとおりです。
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
最近のブラウザ(および一部のレガシーブラウザ)では、次のことが可能です。
Array.isArray(obj)
( Chrome 5、Firefox 4.0、IE 9、Opera 10.5、およびSafari 5でサポートされています)
古いバージョンのIEをサポートする必要がある場合は、 es5-shim を使用してArray.isArrayをpolyfillできます。または以下を追加
# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
};
JQueryを使用している場合は、jQuery.isArray(obj)
または$.isArray(obj)
を使用できます。アンダースコアを使用する場合は、_.isArray(obj)
を使用できます。
異なるフレームで作成された配列を検出する必要がない場合は、instanceof
を使用することもできます。
obj instanceof Array
注 :関数の引数にアクセスするために使用できるarguments
キーワードは、通常は1つのように動作しますが、配列ではありません。
var func = function() {
console.log(arguments) // [1, 2, 3]
console.log(arguments.length) // 3
console.log(Array.isArray(arguments)) // false !!!
console.log(arguments.slice) // undefined (Array.prototype methods not available)
console.log([3,4,5].slice) // function slice() { [native code] }
}
func(1, 2, 3)
これは古い質問ですが、同じ問題を抱えていて、私が共有したい非常にエレガントな解決策を見つけました。
プロトタイプをArrayに追加すると非常に簡単になります。
Array.prototype.isArray = true;
オブジェクトがある場合は、その配列が配列であるかどうかをテストする必要があります。新しいプロパティを確認するだけです。
var box = doSomething();
if (box.isArray) {
// do something
}
isArrayは配列である場合にのみ利用可能です
経由 クロックフォード :
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
Crockfordが言及していない主な失敗は、window
のように、異なるコンテキストで作成された配列を正しく決定できないことです。これでは不十分な場合、そのページにはもっと洗練されたバージョンがあります。
私は個人的にはPeterの提案が好きです: https://stackoverflow.com/a/767499/414784 (ECMAScript 3の場合、ECMAScript 5の場合はArray.isArray()
を使用してください)
ただし、投稿に対するコメントでは、toString()
がまったく変更された場合、その配列チェック方法は失敗することが示されています。本当にtoString()
が変更されておらず、objectsクラス属性に問題がないことを確認したい場合([object Array]
は配列であるオブジェクトのクラス属性です)、次のようにすることをお勧めします。
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]')
{
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
}
else
{
// may want to change return value to something more desirable
return -1;
}
}
JavaScript The Definitive Guide第6版7.10では、ECMAScript 5でArray.isArray()
がObject.prototype.toString.call()
を使用して実装されていることに注意してください。また、toString()
の実装の変更について心配する場合は、他の組み込みメソッドの変更も心配する必要があります。 。なぜPush()
を使うのですか?誰かがそれを変えることができます!そのようなアプローチはばかげています。上記のチェックはtoString()
の変更を心配する人に提供された解決策です、しかし私はチェックが不要であると思います。
この質問を投稿したとき、私が使用していたJQueryのバージョンにはisArray
関数が含まれていませんでした。もしそれがあれば、おそらく私はこの実装を信頼してこの特定の型チェックを実行するための最良のブラウザに依存しない方法であると信頼していたでしょう。
JQueryは現在この機能を提供しているので、私はいつもそれを使用します...
$.isArray(obj);
(バージョン1.6.2現在)それはまだフォーム内の文字列の比較を使用して実装されています
toString.call(obj) === "[object Array]"
EcmaScript 5以降のみを扱っている場合は、組み込みのArray.isArray
関数を使用できます。
例えば。、
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
自分のスクリプトでUnderscore.jsライブラリをすでに使用している可能性がある人のために、もう1つオプションを追加すると思いました。 Underscore.jsにはisArray()関数があります( http://underscorejs.org/#isArray を参照)。
_.isArray(object)
ObjectがArrayの場合はtrueを返します。
Angularを使用している場合は、angular.isArray()関数を使用できます。
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
Crockfordの JavaScript The Good Parts には、与えられた引数が配列かどうかを調べる関数があります。
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
彼は説明する:
まず、値が真実かどうかを尋ねます。これは、nullやその他の偽の値を拒否するために行います。次に、typeof値が 'object'かどうかを尋ねます。これは、オブジェクト、配列、そして(奇妙にも)nullに当てはまります。 3番目に、値が長さプロパティであるかどうかを尋ねます。これは常に配列に当てはまりますが、通常はオブジェクトには当てはまりません。 4番目に、値にスプライスメソッドが含まれているかどうかを尋ねます。これもすべての配列に当てはまります。最後に、lengthプロパティが列挙可能かどうかを尋ねます(lengthはfor inループで生成されますか?)。それはすべての配列に当てはまります。これは私が発見した配列性の最も信頼できるテストです。それがとても複雑であることは残念です。
普遍的な解決策は以下の通りです:
Object.prototype.toString.call(obj)=='[object Array]'
ECMAScript 5以降、正式な解決策は次のとおりです。
Array.isArray(arr)
また、古いJavaScriptライブラリでは、以下の解決策を見つけることができますが、それは十分に正確ではありません。
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
私はこのコード行を使っていました:
if (variable.Push) {
// variable is array, since AMAIK only arrays have Push() method.
}
https://github.com/miksago/Evan.js/blob/master/src/evan.js から参照されるコード
var isArray = Array.isArray || function(obj) {
return !!(obj && obj.concat && obj.unshift && !obj.callee);};
ゴルフをコードする人のために、最も少ない文字での信頼できないテスト:
function isArray(a) {
return a.map;
}
これは通常、階層をトラバース/フラット化するときに使用されます。
function golf(a) {
return a.map?[].concat.apply([],a.map(golf)):a;
}
input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
w3schools :から
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
私はこの小さなコードを作成しました。それは本当の型を返すことができます。
パフォーマンスについてはまだわかりませんが、typeofを正しく識別するための試みです。
https://github.com/valtido/better-typeOf またここにそれについて少しブログを書きました http://www.jqui.net/jquery/better-typeof-than-the-javascript-native- typeof/
現在のtypeofと同様に機能します。
var user = [1,2,3]
typeOf(user); //[object Array]
それはそれが少し微調整を必要とするかもしれないと思う、そして物事を考慮に入れる、私は出くわすか、それを正しくテストしなかった。そのため、パフォーマンスの面でも、typeOfの誤った移植でも、さらなる改善が歓迎されます。
私はブライアンの答えが好きでした:
function is_array(o){
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]') {
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
} else{
// may want to change return value to something more desirable
return -1;
}
}
しかし、あなたはちょうどこのようにすることができます:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
MyObj.constructor == ObjectとmyArray.constructor == Arrayを使うのが最善の方法だと思います。 toString()を使用するよりも約20倍高速です。あなた自身のコンストラクタを使ってオブジェクトを拡張し、それらの生成物を「オブジェクト」と見なすことを望むなら、これはうまくいきませんが、そうでなければその方が速くなります。 typeofはコンストラクタメソッドと同じくらい高速ですが、typeof [] == 'object'はtrueを返しますが、これはしばしば望ましくないでしょう。 http://jsperf.com/constructor-vs-tostring
注意すべき1つのことは、null.constructorはエラーをスローするので、null値をチェックしている可能性がある場合は、最初に次のことを実行する必要があります。(testThing!== null){}