Javascriptでは配列の正しい姿勢を判断します.

4537 ワード

Javascriptでは、変数が配列かどうかをどう判断しますか?
最高の方法はES 5で提供されるArray.isArray()方法です.
var a = [0, 1, 2];
console.log(Array.isArray(a)); // true
しかし、低バージョンIEはES 5をサポートしていないため、互換性が必要なら、他の方法を考える必要があります.typeof配列は特殊なオブジェクトであることを知っています.だから、配列のtypeofもobjectです.nullの結果もobjectなので、typeof演算子を使って配列を判断する必要があります.
var a = [0, 1, 2];
//   object      null、     
console.log(typeof a === 'object' && a !== null && Object.prototype.toString.call(a) !== '[object Object]');  // true
instanceofinstance of演算子の使い方を思い出します.a instance of bは、trueに戻ると、aがbの一例であることを表す.もしa instance of Arayがtrueに戻ると、aが配列タイプということですか?instance ofと同門のconstructorがありますが、同じように判断できますか?
var a = [0, 1, 2];
console.log(a instanceof Array);  // true     ?
console.log(a.constructor === Array); // true   ?
答えは否定です.入れ子frameの場合に注意が必要です.
index.httmコード:
<iframe src='a.htm'></iframe>
<script>
    window.onload = function() {
      var a = window.frames[0].a;
      console.log(a instanceof Array);  // false
      console.log(a.constructor === Array);  // false
    };
</script>
a.httmコード:
<script>
  window.a = [1, 2, 3];
</script>
index.httmコードでは変数aは確かに配列されていますが、a instance of Arayの結果はfalseです.
これは各frameには自分の実行環境があり、frameにまたがって実装されたオブジェクトは互いにプロトタイプチェーンを共有しないからです.a instance of window.frames[0].Arayを印刷すれば、結果はtrueです.
特性チェック
var a = [0, 1, 2];

if (a.sort) {
  //    
}
当てにならないです.もしある対象にソトに値するキーがありますか?
var a = {sort: 'me'};

if (a.sort) {
  //   ?
  //          
}
正しい姿勢はObject.prototype.toString()を使って判断します.
var a = [0, 1, 2];
console.log(Object.prototype.toString.call(a) === '[object Array]'); // true
実際には、これもいくつかのクラスの配列(または他のタイプ)によって判断される主流の方法である.
例えばjQueryで配列判定を行う関連コード(PS:jQuery 1.10.1より抜粋して、最近のバージョンのjQueryはAray.isAray()だけを残しています.ES 5に対応していないブラウザに対しては互換性がありません.
isArray: Array.isArray || function( obj ) {
    return jQuery.type(obj) === "array";
},

type: function( obj ) {
    if ( obj == null ) {
        return String( obj );
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;
},

jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
コードがはっきりしていて、原生をサポートするAray.isAray()のように直接判断し、サポートしない場合はtoString()を呼び出して判断します.他の多くのタイプの変数の判断もToStering()法によるものと見られます.もちろんここで言っているtoString()はすべてObjectのプロトタイプチェーン上のtoString()の方法です.
console.log(Object.prototype.toString.call(10));  // [object Number]
console.log(Object.prototype.toString.call('hello')); // [object String]
console.log(Object.prototype.toString.call(true));  // [object Boolean]
console.log(Object.prototype.toString.call([]));  // [object Array]
console.log(Object.prototype.toString.call({}));  // [object Object]
console.log(Object.prototype.toString.call(function(){}));  // [object Function]
console.log(Object.prototype.toString.call(/a/g));  // [object RegExp]
console.log(Object.prototype.toString.call(null));  // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(new Date())); // [object Date]
Object.prototype.toString()はなぜこのようなタイプの文字列を返しますか?
ECMA-226:
Object.prototype.toString( ) When the toString method is called, the following steps are taken: 
1. Get the [[Class]] property of this object. 
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”. 
3. Return Result (2) 
上記の仕様では、Object.prototype.toStringの挙動を定義しています.まず、対象の内部属性[Class]を取得し、この属性に基づいて、「[object Aray]」と似た文字列を結果として返します.この方法を利用して、またコールに協力して、私達はいかなる対象の内部の属性[クラス]を得ることができて、そしてタイプの検査を文字列の比較に転化して、私達の目的を達成します.まずはECMA標準でのアラyの説明を見てみましょう.
new Array([ item0[, item1 [,…]]]) 
The [[Class]] property of the newly constructed object is set to “Array”.
したがって、Javascriptでは、配列を判断する関数はこう書くことができます.
function isArray(a) {
  Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';
}
リードMore:
  • Javascript配列タイプ検出:より強力なisAray関数
  • を作成する.
  • JavaScript:Object.prototype.toString方法の原理