JavaScriptの値の型を判定しよう! typeofの使い方を徹底解説

こんにちは!Webコーダー・プログラマーの貝原(@touhicomu)です。

JavaScriptのコードを書く際に、変数の型を知りたいときってよくありますよね。
また、どのクラスのインスタンスなのかを知りたい場合も多いです。

今回はそんな時に使える、JavaScriptのtypeofについて解説したいと思います。

この記事は下記の流れで解説していきます。

【基礎】そもそも型とは?
【基礎】typeofの基本的な型判定方法
【発展】typeofで配列やラッパークラスを判定する方法
【発展】typeofとinstanceofの違い

typeofの使い方をマスターし、正しい場面で使いこなせるよう、しっかり学習を進めていきましょう。

目次

そもそも型とは?

JavaScriptの型判定について解説する前に、そもそも型(かた)とはどんなものなのか、きちんと理解するところから始めましょう。

プログラミングの世界に限らず日常の世界でも”文字”という言葉は色々なものを指しますよね。
日本語のひらがなや英語、それに数字など様々な種類に分類されます。

プログラミングの世界でもコンピュータが扱う”データ”という言葉が指すものとして、いくつかの種類が存在しています。
その種類のことを一般的に”型”と呼んでいます。

例えば、日本語の”おはよう”という文字のデータは文字列型(もしくはString型)と呼ばれ、数字の1や100などは数値型と呼ばれています。

さらにその中で、JavaScriptの基本的な型のことを組み込み型(もしくはプリミティブ型)と呼んでいます。

今回やるような判定の際は、下記のような型がよく使われています。
まだこれでも一部ですが、ひとまずこれだけ押さえておけばOKです。

型名値の例判定で表示される値備考
数値型1,2,3などnumber
文字列型おはよう、abcなどstringString型とも呼ばれる
真偽値型True / Falseboolean
Null型nullobject
Undefined型undefinedundefined何も代入されていない変数に設定されている値
関数function() {}function
他のオブジェクト{a: 1}object

型には本当に色々な種類があります。
一気に覚えるのは大変だと思うので、必要な時に確認してみるといいですね。

型を判定するtypeofの使い方

型の種類についてバッチリ理解できたところで、型の判定方法について確認していきましょう。

型の判定には、typeofという演算子を使います。

基本的な書き方は下記のように、typeofの後ろに型を判定したい値を記述するだけです。

typeof 判定したい値

では、これを使って様々な型を判定して、より理解を深めていきましょう。

組み込み型(プリミティブ型)の場合

typeof演算子で判定するものとして、まずは、文字列や数値型などの組み込み型(プリミティブ型)のtypeofの判定結果を見ていきましょう。

window.onload = function () {
    // typeofの使用例

    // Number
    console.log( 'typeof 1 = ' + (typeof 1) );
    console.log( 'typeof 1.41 = ' + (typeof 1.41) );
    console.log( 'typeof Math.PI = ' + (typeof Math.PI) );
    console.log( 'typeof Infitity = ' + (typeof Infinity) );

    // String
    console.log( 'typeof "" = ' + (typeof "") );
    console.log( 'typeof "abc" = ' + (typeof "abc") );
    console.log( 'typeof "123" = ' + (typeof "123") );
    console.log( 'typeof (typeof 0) = ' + (typeof (typeof 0)) );

    // Boolean
    console.log( 'typeof true = ' + (typeof true) );
    console.log( 'typeof false = ' + (typeof false) );

    // Undefined
    console.log( 'typeof undefined = ' + (typeof undefined) );
}

実行結果:

// Number
typeof 1 = number
typeof 1.41 = number
typeof Math.PI = number
typeof Infitity = number

// String
typeof "" = string
typeof "abc" = string
typeof "123" = string
typeof (typeof 0) = string

// Boolean
typeof true = boolean
typeof false = boolean

// Undefined
typeof undefined = undefined

以上のように、組み込み型に対して、typeofは正しく動作しているようですね。

また、「typeof (typeof 0) = string」となっているように、typeofの返り値はstring型であることがわかります。

関数やオブジェクト型の場合

次は、関数やオブジェクトに対するtypeofの結果を見ていきましょう。

window.onload = function () {
    // Function
    console.log( 'typeof function () { } = ' + (typeof function () { }) );
    console.log( 'typeof class abc { } = ' + (typeof class abc { }) );
    console.log( 'typeof Math.abs = ' + (typeof Math.abs) );

    // Object
    console.log( 'typeof { prop: 1 } =' + (typeof { prop: 1 }) );

    // nullはObject型です。
    console.log( 'typeof null = ' + (typeof null) );

    // Date()やString()のラッパーオブジェクトはObjectと判定されます。
    console.log( 'typeof new String("abc") = ' + (typeof new String("abc")) );

    // Array は Objectと判定されます。
    console.log( 'typeof [1, 2, 3] = ' + (typeof [1, 2, 3]) );

    // Array.isArray や Object.prototype.toString.call などで
    // 普通のオブジェクトと配列を区別できます。
    console.log( 'Array.isArray({ prop: 1 }) = ' + (Array.isArray({ prop: 1 })) );
    console.log( 'Array.isArray([1, 2, 3]) = ' + Array.isArray([1, 2, 3]) );
}

実行結果:

// Function
typeof function () { } = function
typeof class abc { } = function
typeof Math.abs = function

// Object
typeof { prop: 1 } =object

// nullはObject型です。
typeof null = object

// Date()やString()のラッパーオブジェクトはObjectと判定されます。
typeof new String("abc") = object

// Array は Objectと判定されます。
typeof [1, 2, 3] = object

// Array.isArray や Object.prototype.toString.call などで
// 普通のオブジェクトと配列を区別できます。
Array.isArray({ prop: 1 }) = false
Array.isArray([1, 2, 3]) = true

関数やクラス、Mathの組み込み関数などは、"function"と判定されていますね。

また、オブジェクトは"object"と正しく判定されていますが、配列やラッパークラスも”object”と判定されています。

ラッパーオブジェクトは、組み込み型をオブジェクト化したものですので、"object"と判定されてしまうのです。
これでは厳密な判定とは言えませんね。

そんな時、はArray.isArray()メソッドを使えば、配列の場合はtrue、配列以外の場合はfalseを返してくれます。

配列やラッパークラスを判定する

typeofでは、ラッパーオブジェクトがObjectと判定され、ArrayもObjectと判定されていました。

もっと細かく判定ができるよう、これらを改善する関数を作ってみましょう。

下記のgetClassName()という関数を作成してみました。

window.onload = function () {
    //typeofの関数化の例
    function getClassName(obj) {
        if (typeof obj === "undefined") {

            // objがundefined
            return "undefined";

        } else if (obj === null) {

            // objがnull
            return "null";

        } else {

            // objが有効
            // prototype名取得
            var className = Object.prototype.toString.call(obj);

            // "object"以降のクラス名を取得
            var matches = className.match(/^[objects(.*)]$/);
            if (matches.length > 0) {

                // クラス名が存在
                return matches[1];

            } else {

                return className;

            }
        }
    }
}

引数がundefinedかnullの場合は、いずれもオブジェクトではないのでそのまま返り値にしています。
この判断にtypeofを使用しています。

nullかどうかは、オブジェクトに===演算子を使って直接nullかを判断するようにしました。

それ以外の場合はprototype名を取得し、その中から正規表現にてクラス名を抜き出しています。
これは、typeofの機能ではありません。

では、作成した関数を以下のコードで判定してみましょう。

window.onload = function () {
    console.log( 'getClassName("") = ' + getClassName("") );
    console.log( 'getClassName(true) = ' + getClassName(true) );
    console.log( 'getClassName(0) = ' + getClassName(0) );

    // ArrayもArrayと判定できる。
    console.log( 'getClassName([1,2,3]) = ' + getClassName([1,2,3]) );
    console.log( 'getClassName({a: 1}) = ' + getClassName({a: 1}) );
    console.log( 'getClassName(null) = ' + getClassName(null) );

    var FuncA = function (a) { return a; };
    console.log( 'getClassName(FuncA) = ' + getClassName(FuncA) );
}

実行結果:

getClassName("") = String
getClassName(true) = Boolean
getClassName(0) = Number

// ArrayもArrayと判定できる。
getClassName([1,2,3]) = Array
getClassName({a: 1}) = Object
getClassName(null) = null

getClassName(FuncA) = Function

以上のように、組み込み型およびArrayについてもそのクラス名を取得できています。

また、関数のクラス名も取得できていますね。

類似メソッドinstanceofとの違い

typeof演算子と似たような判定処理を行う演算子にinstanceof演算子があります。

instanceof演算子はオブジェクトがどのクラスのインスタンスかを判定する際に使用します。

使い方は簡単、instanceofに続けて調べたいオブジェクトを指定するだけです。

window.onload = function () {
    // instanceofの使用例
    var arrayData = [1, 2, 3, 4, 5];

    console.log( 'arrayData instanceof Array =' + (arrayData instanceof Array) ); 
    console.log( 'arrayData instanceof Object = ' + (arrayData instanceof Object) );

    // 組み込み型(プリミティブ型)にはinstanceofは効かない。
    console.log( '1 instanceof Number = ' + (1 instanceof Number) );
    console.log( '"abc" instanceof String = ' + ("abc" instanceof String) );
    console.log( 'true instanceof Boolean = ' + (true instanceof Boolean) );

}

実行結果:

arrayData instanceof Array =true
arrayData instanceof Object = true

 // 組み込み型(プリミティブ型)にはinstanceofは効かない。
1 instanceof Number = false
"abc" instanceof String = false
true instanceof Boolean = false

以上のように、配列は、ArrayとObjectのインスタンスでした。
これはArrayがObjectを継承したオブジェクトだからですね。

また、組み込み型には、instanceofは使用できませんでした。

これは、組み込み型はオブジェクトを継承した"もの(オブジェクト)"ではなく、単なる"値"なので、組み込み型がなんらかのオブジェクトのインスタンスになることはないからです。

まとめ

いかがでしたか?
typeof演算子は、変数の型を取得するのに便利ですね。

最後に、ポイントをおさらいしておきましょう。

・組み込み型のラッパークラスに対してはうまく動作しない
・instanceof演算子は、オブジェクトがどのインスタンスなのかの判定ができる
・組み込み型のラッパークラスも正しく判定できている
・typeof演算子をうまく関数化すれば便利なコードができる

皆さんもぜひ、ご自分で関数化してみてください。

使い方を忘れてしまったら、是非この記事を思い出してくださいね。

この記事を書いた人

【プロフィール】
DX認定取得事業者に選定されている株式会社SAMURAIのマーケティング・コミュニケーション部が運営。「質の高いIT教育を、すべての人に」をミッションに、IT・プログラミングを学び始めた初学者の方に向け記事を執筆。
累計指導者数4万5,000名以上のプログラミングスクール「侍エンジニア」、累計登録者数1万8,000人以上のオンライン学習サービス「侍テラコヤ」で扱う教材開発のノウハウ、2013年の創業から運営で得た知見に基づき、記事の執筆だけでなく編集・監修も担当しています。
【専門分野】
IT/Web開発/AI・ロボット開発/インフラ開発/ゲーム開発/AI/Webデザイン

目次