Javascriptのオブジェクト判別方法
Javascriptのオブジェクト判別法歩をまとめてみました。
まとめてみました理由としてはJavascriptで厳密なクラス等の判別が正しくできなかったため、厳密な判別方法を模索しました。
調べてみると意外な結果がわかりました。
オブジェクトの判別方法
簡単にオブジェクトを判別する方法は以下の方法になります。
ちなみに結果は全てtrueになります。
// オブジェクトの生成 var obj = new Object(); //オブジェクトを文字列化 console.log(Object.prototype.toString.call(obj) == '[object Object]'); // true //オブジェクトの種別判断 console.log(Object.prototype.isPrototypeOf(obj)); // true //データ型の返却 console.log(typeof obj == 'object'); // true //オブジェクトのコンストラクタを比較 console.log(obj instanceof Object); // true
ここのあたりはJavascriptを使用する人ならどれかは使ったことあるはずです。
参考に各比較の厳密の説明は下記のリンクを参照してみてください。
ここからが問題でObject型を拡張したString、Date型の場合いくつか問題が発生。
サンプル例はDate型で試してみます。
// オブジェクトの生成 var date = new Date(); //オブジェクトを文字列化 console.log(Object.prototype.toString.call(date) == '[object Date]'); // true //オブジェクトの種別判断 console.log(Date.prototype.isPrototypeOf(date)); // true //データ型の返却 console.log(typeof date == 'object'); // true //オブジェクトのコンストラクタを比較 console.log(date instanceof Date); // true
この時点で既にtypeofを使用した場合にobjectじゃないとtrueにならないと言うことがわかります。
このため、厳密なオブジェクトの判別を行いたい場合の方法を模索しました。
厳密なオブジェクトの判別
Javascriptでエラーを出さないためにも厳密なオブジェクトの判別を行いたいので色々調べてみました。
前述した型の判別で既にtoStringは返却値が文字列、typeofに関してはDate型に対して親のobjectとして型名が返却されるので除外して考えてみます。
// オブジェクト生成 var obj = new Object(); // 親オブジェクト生成 var superObj = new Object(); // 子オブジェクト生成 var subObj = Object.create(superObj); console.log(subObj instanceof obj.constructor); // true console.log(subObj instanceof superObj.constructor); // true console.log(obj.isPrototypeOf(subObj)); // false console.log(superObj.isPrototypeOf(subObj)); // true
上記の結果を見てもらえばわかるかと思いますが、superObjの子クラスのsubObjが「instanceof」で比較した際にはobjともsuperObjともtrueになります。
これは「instanceof」がコンストラクタで比較を行うために同じObject型だったためtrueになります。
「isPrototypeOf」で判定を行いますとこれは「subObj」が「superObj」由来のprototypeかどうかを判定しているためtrueになり、「obj」との比較時にはfalseになります。
このあたりの違いを厳密にしないと型の判別を行ったら想定とは別の方だったとかありえそうで怖いです・・・
今まで型のチェックに「instanceof」を基本的に使用していたので今考えると厳密にチェックできていない箇所が存在したのかもと思うとバグの原因になりえそうです。
出来るだけ正確なチェックを行えばバグは発生しにくくなるかと思います。
«前の記事:Webアプリを作成する際のデバイス対応の話新人さん、質問は5W1Hでお願いします。:次の記事»