JavaScriptで変数がオブジェクトか配列かを判断する方法
この作業では、変数がオブジェクトなのか、配列なのかを判断する問題が必ず出てきます。
基本
JavaScriptの変数型は
このように、JavaScriptには全部で8つの型があり、大きく分けて基本型と参照型があります。
typeof演算子
typeof 演算子は、未計算のオペランドの型を示す文字列を返します。
typeofによって返されるすべての結果を下図に示します。
JavaScriptの型とtypeofの対応関係
JavaScriptの型とtypeofの対応を下図に示します。 typeofの戻り値とJavaScriptの型は1対1対応ではありません。
変数がオブジェクトかどうかを判断する方法
判定にはtypeofを使用します。
typeofが'object'を返す場合、その変数はObjectかNullのどちらかであることが説明でわかりました。コードを以下に示します:
isObject = obj => obj !== null && obj === 'object'
Object.prototype.toStringを使用することで、配列が型であることを確認できます。.prototype.toString判定
typeofを使って変数がオブジェクトかどうかを判断する方法はすでに説明しましたが、typeofを次のように使うことには問題があります。
console.log(typeof {a: 'a', b: 'b'}) // object
console.log(typeof Promise.resolve()) // object
console.log(typeof new Date()) // object
console.log(typeof [1, 2, 3]) // object
isObject関数を使用して変数を判定する場合、{a: 'a', b: 'b'}のようなオブジェクトだけでなく、配列、Promise、Dateのような組み込みコンストラクタが返すオブジェクトも判定を通過します。しかし、ある変数がJavaScriptの様々な組み込みコンストラクタによって生成されたオブジェクトではなく、{a: 'a', b: 'b'}のような純粋なオブジェクトかどうかを判定したい場合、typeofメソッドが手薄になるケースがあります。
変数が純粋なオブジェクトかどうかを判断するには、以下のコードに示すように、Object.prototype.toStringメソッドを使用します:
const isPlainObject = obj => Object.prototype.toString.call(obj) === '[object Object]'
obj.toStringの代わりにObject.prototype.toStringが使用される理由は、オブジェクトのプロトタイプによってはtoStringメソッドをオーバーライドする場合があるため、Object.prototype.toStringメソッドを呼び出すことを示すことが重要だからです。
オブジェクトが空かどうかを判断する方法
JavaScriptのプロジェクトでは、多くの場合、変数がヌルオブジェクトであるかどうかを判断する必要があるので、どのようにヌルオブジェクトの判断を実装するには?
for inループを使って
function isEmptyObj(obj) {
for (let i in obj) {
return false
}
return true
}
for inループは、現在のオブジェクトとオブジェクト・プロトタイプの列挙可能なプロパティを繰り返し処理します。
オブジェクトに列挙不可能な属性しかない場合、このメソッドはエラーになります。
Object.prototype.toStringを使用することで、配列が型であることを確認できます。.keysメソッド判定
このメソッドの核心は、空のオブジェクト自体にはプロパティがないため、オブジェクト自身のプロパティを取得し、その結果がnullであれば空のオブジェクトであるということです。
const isEmptyObj = obj => Object.keys(obj).length === 0
Object.keysは、オブジェクト自身のすべての列挙可能なプロパティの名前を配列で返しますので、配列の長さが0であれば、それは空のオブジェクトです。
短所:for inループを使った判定と同様、Object.keysメソッドは列挙可能なプロパティしか返さないので、完璧ではありません。
Object.prototype.toStringを使用することで、配列が型であることを確認できます。.getOwnPropertyNamesメソッド判定
const isEmptyObj = obj => Object.getOwnPropertyNames(obj).length === 0
このメソッドはObject.keysを改良したもので、オブジェクト自身のプロパティ名の配列を返します。ただし、Object.keys とは異なり、列挙不可能なプロパティを取得することができます。
欠点:このメソッドでは、シンボルで表される属性を取得できません。コードは以下のようになります:
const isEmptyObj = obj =>
Object.getOwnPropertyNames(obj).length === 0 && Object.getOwnPropertySymbols(obj).length === 0
Reflectの使用.ownKeysメソッド判定
また、Reflect.ownKeysを使用して、オブジェクト自身のプロパティの名前の配列を返すこともできます。これは、通常のプロパティ名だけでなく、列挙不可能なプロパティやSymbolプロパティも返します。
const isEmptyObj = obj => Reflect.ownKeys(obj).length === 0
変数が配列かどうかを判断する方法
1つはArray.isArrayメソッドを使う方法で、もう1つはObject.prototype.toStringメソッドを使う方法です。
Array.isArrayを使うことで、この2つのメソッドをカプセル化することができます。.isArray
Array.isArrayメソッドは、オブジェクトが配列であるかどうかを判定するための新しいES6メソッドです。コードは以下の通りです:
const isArray = obj => Array.isArray(obj)
Object.prototype.toStringを使用することで、配列が型であることを確認できます。.prototype.toString
const isArray = obj => Object.prototype.toString.call(obj) === '[object Array]'
完璧なソリューション
Array.isArrayとObject.prototype.toStringを使用して配列が型であるかどうかを判断することは可能ですが、Array.isArrayはES6の構文であり、これらの2つのメソッドをカプセル化して完璧なソリューションを形成することができます:
function isArray(obj) {
if (Array.isArray) {
return Array.isArray(obj)
} else {
return Object.prototype.toString.call(obj) === '[object Array]'
}
}





