読者です 読者をやめる 読者になる 読者になる

tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

javascriptで配列かどうか判定するメモ(ダックタイピングとかObject.prototype.toStringとかgetPrototypeOfとかinstanceofで)

はじめに

前に javascriptでオブジェクト({ }とか連想配列であるobject)の判定をしたいがnullや配列([ ])に悩まされる問題をまじめに自分用まとめ という記事を書きました。
コメントでご指摘頂いたこともあって配列の判定に関してこちらの記事で別途try!

ながれ

  1. ダックタイピングで配列を判定
  2. Object.prototype.toStringで配列を判定+α
  3. getPrototypeOfで配列を判定
  4. instanceofで配列を判定

てことでさっそく

1. ダックタイピングで配列を判定

まず、ダックタイピングがうまく説明できる自信ないのでwiki先生より抜粋

ダックタイピング
オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、
たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる

詳しくはソースでみてもらうとして、
今回は配列として下記のインターフェースを持ってるものとする、と決めました

判別する変数をoとして

  • typeof o === "object"がtrueである
  • oはpopメソッドを持っている
  • oはjoinメソッドを持っている
  • (interfaceじゃないけど)o != nullがtrueである
  • sample01

判定順ですがo != nullを判定の最後に置いた場合、
'pop' in oとかでエラーになるので最初にもってきてます

2. Object.prototype.toStringで配列を判定+α

今度はObject.prototype.toStringメソッドをcallを使って呼び出すことで判別する方法です。
このメソッドはcallに与えた引数に対して、文字列として[object` + class + `]を返却するのでそれを使います

  • sample02
+α

JavaScript 1.8.5ではArray.isArrayが実装されています。
こちらの中身はこんな感じ

if(!Array.isArray) {  
  Array.isArray = function (vArg) {  
    return Object.prototype.toString.call(vArg) === "[object Array]";  
  };  
}

Object.prototype.toString.callは推奨っぽいので良さげです。

3. getPrototypeOfで配列を判定

getPrototypeOfの説明は他サイトにお任せ

Object.getPrototypeOf( object )メソッドは、引数「object」に指定したオブジェクトのプロトタイプを参照するメソッド
Object.getPrototypeOf( object )メソッド

ということで、これを使って配列の判定をしてみます

  • sample03

4. instanceofで配列を判定

こちらは王道っぽいですが、前の記事でやってるのと、
実行時型判定の問題で判定が弱いとの記事もあり最後にしておきました
判定が弱い問題については参考サイトとソースを後述します

まずは普通に

  • sample04
問題

実行時型判定のため、フレームが違う場合instanceofを使っても判定が意図しない結果になる
ということがあるのでこちらものっけときます

  • sample05

結果として2つ載せてますが、両方ともarr instanceof Array的なやつがfalseになります。
これは正直盲点でしたΣΣ(゚д゚lll)

こちらを参考にさせて頂きました
JavaScript配列検出で起こる問題について ─── 型判定の基礎

まとめ

ってことで配列の判定にのみ絞って方法をいくつか試してみました。
厳密に配列だけを判定って機会は少ないかもですが何かの役に立てば!
\(^o^)/

一応コレを書く元となった記事のせときます
javascriptでオブジェクト({ }とか連想配列であるobject)の判定をしたいがnullや配列([ ])に悩まされる問題をまじめに自分用まとめ