構文

【JavaScript】 typeof演算子は何を返しているのか?

更新日:2021/07/08

JavaScriptのtypeof演算子を使用すると、値の型チェックをおこなうことができます。
しかし少しクセが強い演算のため、わかりにくい面があります。

そこで今回は、typeof演算子について解説してみます。

 

typeof演算子とは

typeof演算子について、簡単に解説します。

typeof演算子は文字列を返す

typeof演算子は、値の型を文字列で返します。

例えば数値に対してtypeof演算を行うと、文字列"number"を返します。
文字列に対してtypeof演算を行うと、文字列"string"を返します。

typeof演算子の例


console.log( typeof 123 ); // "number"
console.log( typeof "abc" ); // "string"

typeof演算子による型チェック

typeof演算子が決まった文字列を返す特性を利用して、値の型チェックをおこなうことができます。

例えば変数が数値(Number型)のとき処理をおこないたいなら、次のようにコードを記述します。

変数が数値のとき処理をおこなう


const value = 123;

if( typeof value === "number" ) { /* 処理 */ }

文字列の比較なので、"Number"とか、"NUMBER"などではダメです。

わざわざ文字列比較しなければいけない点に迂遠な印象を受けますが、仕様なので仕方がありません。
構文として覚えておきましょう。

typeof演算子とオブジェクト

そしてオブジェクトに対してtypeof演算を行うと、文字列"object"を返します。

typeof演算子でオブジェクトを指定


console.log( typeof {} ); // "object"

しかし、関数(functionオブジェクト)は同じオブジェクトなのに、"function"を返します。

typeof演算子で関数を指定


console.log( typeof function(){} ); // "function"
console.log( typeof (()=>{}) ); // "function"

なんだか統一感がありませんし、他にも特例なものがありそうで少し使いにくく感じますね。

 

パターンは少ない

typeof演算子のアルゴリズムを確認してみると、次表に従って文字列を返しているだけということがわかります。。

typeof演算子のアルゴリズムはこちら
12.5.5 typeof演算子(The typeof Operator)

値の型返す値
Undefined"undefined"
Null"object"
Boolean"boolean"
Number"number"
String"string"
Symbol"symbol"
BigInt"bigint"
関数以外のObject"object"
関数Object"function"

それほどパターンは多くないですね。

UndefinedとNull

通常UndefinedNullのチェックは、typeof演算子を使用しません。

次のように値で直接確認できます。

UndefinedとNullのチェック


if( value === undefined ) { /* 処理 */ }
if( value === null ) { /* 処理 */ }

Object

オブジェクトで特例なのは、関数だけのようです。
しかし表をよく見ると、Nullのときも"object"を返しているのがわかります。

つまり、typeof演算子が"object"を返しても、オブジェクトと判断できないということです。
次のようにnullとの比較も必要です。

オブジェクトかどうかの確認


if( value !== null && typeof {} === "object" ) { /* 処理 */ }

オブジェクトとプリミティブ

上の表ではString型は、"string"と返すことになっています。
ここで勘違いしてはいけないのが、検査対象がプリミティブの時だけだということです。

JavaScriptにはStringオブジェクトというものがあります。
これとは、別だということです。
Stringオブジェクトはオブジェクトなので、typeof演算子は"object"を返します。

Stringオブジェクトは"object"を返す


console.log( typeof "abc" ); // "string"
console.log( typeof new String("abc") ); // "object"

BooleanオブジェクトとNumberオブジェクトも同じように、"object"を返します。

Stringオブジェクトは"object"を返す


console.log( typeof new Boolean(true);); // "object"
console.log( typeof new Number(123);); // "object"

なおSymbolとBigIntは、対応するオブジェクトをコード上で生成することができません。
生成されるのは、メソッドを実行するためにプリミティブ値が対応するオブジェクトに変換された時だけです。

そのため、上記のような比較は想定されません。

オブジェクトの種類の確認

型チェックに関連して、オブジェクトの種類を確認するケースが考えられます。
例えば、配列(Arrayオブジェクト)かどうかをチェックしたいときです。

この場合は、instanceof演算子を使用します。

配列かどうかの確認


const array = [];
console.log( array instanceof Array ); // true

JavaScript初心者のうちは、typeofかinstanceofか、どちらを使用すればいいのかわかりにくいです。
とりあえず、上の表に当てはまらないときは、instanceofを使用すると覚えておくといいです。

 

JavaScriptデータ型とtypeof演算子の不一致

JavaScriptの仕様では、全部で8つのデータ型が定義されています。

JavaScriptデータ型データ値
Undefined型

undefined値
Null型

null値
Boolean型

真偽値(trueまたはfalse)
String型

文字列値
Symbol型

シンボル
Number型

数値
BigInt型

長整数値
Object型

オブジェクト値

typeofは値の型を返す演算子なので上記の表に沿った結果となるべきですが、少しアレンジが加えられています。
上の表に、typeof演算の結果を加えてみます。

JavaScriptデータ型データ値typeof演算結果
Undefined型

undefined値"undefined"
Null型

null値"object"
Boolean型

真偽値(trueまたはfalse)"boolean"
String型

文字列値"string"
Symbol型

シンボル"symbol"
Number型

数値"number"
BigInt型

長整数値"bigint"
Object型

オブジェクト値(関数以外)"object"
オブジェクト値(関数)"function"

赤文字が、本来のデータ型と異なる型名です。

これを見ると、typeof null の演算結果が "object" になるのは奇妙に感じますね。

理由を調べてみると、仕様作成時の記述間違い(仕様バグ)や、当時はオブジェクトの空参照にnullを使っていたので "object" を返すのは理にかなっているなど理由が挙げられていました。

しかしJavaScriptの仕様でtypeofの項目を読むと、typeofが何を目的とした演算子なのかが明記されていません。
書いてあるのはアルゴリズムだけです。

typeof演算子のアルゴリズムはこちら
12.5.5 typeof演算子(The typeof Operator)

つまりtypeof演算子はデータの型を返しているのではなくて、対象となる値ごとに何らかの文字列を返しているだけと言えます。

深く考えずに、「そういうものなんだ」で納得しておけばいいという話かもしれませんね。

更新日:2021/07/08

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。