####型判定について調べることがあったので、まとめてみました。
#先に結論から
型判定にはObject.prototype.toString.call()
を使うと幸せになれる。
#型の種類
JavaScriptは動的型付け言語のため、静的型付け言語のような変数の型はありません。
しかし、文字列や真偽値のような値の型は存在します。
この値の型はデータ型と呼ばれ、大きく分けて下記の2つに分類されます。
##プリミティブ型(基本型)
- Boolean(真偽値)
-
true
とfalse
の2つがある - String(文字列)
-
"あいうえお"
などのテキストデータ - Number(数値)
-
42
や3.14159
などの数値のデータ - null
- 値が存在しないことを意味する。
null
の1種類しかない - undefined
- 値が未定義であることを意味する
- Symbol
- ES2015から追加された一意で不変な値を意味する(正直使い所がよくわかっていない。。)
- BigInt(巨大な整数)
- ES2020から追加された
9007199254740992n
などの任意の精度で精度で表すことができる(正直使い所がよくわかっていない。。)
##オブジェクト型(複合型)
- プリミティブ型以外のデータ
- オブジェクト、配列 関数、正規表現、Dateなど
#型判定してみる
typeof
演算子を使うと型を調べることができる
console.log(typeof true); // boolean
console.log(typeof "あいうえお"); // string
console.log(typeof 1234); // number
console.log(typeof null); // object (なぜ?!?!)
console.log(typeof undefined); // undefined
console.log(typeof Symbol("シンボル"));// symbol
console.log(typeof 9007199254740992n); // bigint
console.log(typeof ["hoge", "fuga"]); // object (なぜ?!?!)
console.log(typeof { "key": "value" }); // object
console.log(typeof function() {}); // function
console.log(typeof(new Date())); // object (なぜ?!?!)
console.log(typeof(new Array())); // object (なぜ?!?!)
##typeof
では厳密な判定が出来ない問題
判定結果を見ると、null
や配列やnew
した際にobject
として判定されてしまう。。。。
これでは細かなオブジェクト型の判定はできなく、配列/null/日付等の区別もできない
ちなみに、typeof null
がobject
と判定されてしまうのは、歴史的経緯のある仕様のバグ1らしい(初めて知った)
##Object.prototype.toString.call() を使って厳格な型判定をする
const toString = Object.prototype.toString;
console.log(toString.call(true)); // [object Boolean]
console.log(toString.call("あいうえお")); // [object String]
console.log(toString.call(1234)); // [object Number]
console.log(toString.call(undefined)); // [object Undefined]
console.log(toString.call(Symbol("シンボル"))); // [object Symbol]
console.log(toString.call(9007199254740992n)); // [object BigInt]
console.log(toString.call(["hoge", "fuga"])); // [object Array]
console.log(toString.call({ "key": "value" })); // [object Object]
console.log(toString.call(function() {})); // [object Function]
console.log(toString.call(new Date())); // [object Date]
console.log(toString.call(new Array())); // [object Array]
-
JavaScriptが最初にNetscapeで実装された際にtypeof null === "object"となるバグがありました。このバグを修正するとすでにこの挙動に依存しているコードが壊れるため、修正が見送られ現在の挙動が仕様となりました。 詳しくは https://2ality.com/2013/10/typeof-null.html 参照。 ↩