【入門編】 Object.prototype.toString.call()による詳細な型判定 – JavaScript実践ガイド

JavaScriptの世界へようこそ!
日々コードを書いていると、「あれ、今この変数の中身って何だっけ?」と頭を抱えたくなる瞬間、必ず訪れますよね。

特に、画面から取得したデータや、どこからか飛んできたAPIのレスポンスを扱うとき、「これ、配列だと思ってたのに中身がオブジェクトだった……!」なんてバグに直面して、冷や汗をかいた経験はありませんか?

大丈夫です。誰もが最初はそこでつまずきますし、JavaScriptの「型」の気まぐれさに翻弄されるのは、一人前のエンジニアへの通過儀礼のようなものです。

今日は、そんなJavaScriptの「これなんだっけ?」を華麗に解決する、ちょっと玄人っぽくて、でもめちゃくちゃ頼りになる秘密兵器`Object.prototype.toString.call()`について、優しく紐解いていきましょう!

—

犯人は「typeof(タイトオフ)」という名の、ちょっとおせっかいだけど頼りない警備員

JavaScriptには、変数の型を調べるための `typeof` という一番有名な演算子があります。まずはこいつの性格を知っておきましょう。

例えるなら、`typeof` は「ざっくりとした仕分けをする空港の保安検査員」のようなものです。
「人間か、荷物か」「金属を持っているか、いないか」くらいの大まかな判断は大得意ですが、細かい違いまでは見分けてくれません。

実際にコードで見てみましょう。

// さまざまなデータを用意してみます
const a = “こんにちは”;
const b = [1, 2, 3]; // 配列
const c = { name: “タロウ” }; // オブジェクト
const d = new Date(); // 日付

console.log(typeof a); // “string” (文字列だね、OK!)
console.log(typeof b); // “object” (……あれ?配列なのに “object”?)
console.log(typeof c); // “object” (うん、これはオブジェクト)
console.log(typeof d); // “object” (えっ、日付も “object” なの!?)

そうなんです! `typeof` さんは、配列(Array)を見ても、日付(Date)を見ても、地図(Map)を見ても、全部まとめて `”object”` と答えてしまうんです。これでは「配列専用の処理をしたいのに!」というときに困ってしまいますよね。

—

救世主登場!『Object.prototype.toString.call()』という名の鑑識官

ここで登場するのが、今回の主役である `Object.prototype.toString.call()` です。
名前がやたらと長くて呪文のようですが、怖がらなくて大丈夫です。

先ほどの空港の保安検査員(`typeof`)が「ざっくり屋」だとしたら、こちらは「現場の隅々まで見逃さない、超優秀な鑑識官」です。

この鑑識官は、どんなデータが持ち込まれても、その本質を暴き出し、次のようなフォーマットの「身分証明書」をきっちり発行してくれます。

`[object タイプの名前]`

百聞は一見に如かず。実際にこの鑑識官を呼んで、先ほどのデータたちを調べてみましょう。

// さっきのデータたちに、鑑識官(Object.prototype.toString.call)を派遣します

const a = “こんにちは”;
const b = [1, 2, 3];
const c = { name: “タロウ” };
const d = new Date();

console.log(Object.prototype.toString.call(a));
// 出力結果: “[object String]” (おっ、文字列だねと即座に判別!)

console.log(Object.prototype.toString.call(b));
// 出力結果: “[object Array]” (お見事!配列であることを正確に見抜きました!)

console.log(Object.prototype.toString.call(c));
// 出力結果: “[object Object]” (プレーンなオブジェクトですね)

console.log(Object.prototype.toString.call(d));
// 出力結果: “[object Date]” (日付データであることも一発で分かります!)

すごいでしょう? `typeof` では全部 `”object”` で片付けられていたものたちが、綺麗にそれぞれの本当の姿を現しました。これなら安心してお仕事ができますよね。

—

なんでこんなに長いの?仕組みをこっそり覗いてみよう

「でも先生、なんでこんなに長い書き方なんですか? `toString()` だけじゃダメなの?」

そう思ったあなたは素晴らしい着眼点を持っています。
実は、JavaScriptのすべてのデータ(正確にはオブジェクトの仲間たち)は、大元をたどると全員 `Object` という共通の先祖を持っています。そして、その先祖全員が `toString()` という「私を文字列にしてね」と言える共通のスキルを持っています。

ただ、ここで少し問題があります。
配列(Array)や日付(Date)といった子供たちは、それぞれ自分用にそのスキルを「独自にカスタマイズ(上書き)」してしまっているんです。そのため、配列に対して普通に `.toString()` を呼ぶと、中身の要素をカンマ繋ぎの文字列にして返してしまいます(例: `[1, 2, 3].toString()` は `”1,2,3″` になっちゃいます)。

そこで、こう頼むのです。
「君のカスタマイズしたスキルは使わないで、大元(Object)の本来のやり方で、私の渡したデータを調べ直して(callして)くれ!」

これが、`Object.prototype.toString.call(調べたいもの)` という呪文の正体です。
今は深く考えすぎず、「JavaScript界の由緒正しい、一番正確な身分証明書の出し方なんだな」と覚えておけばバッチリです!

—

実務でどう使うの?便利な判定関数の作り方

さて、この強力な呪文ですが、毎回 `Object.prototype.toString.call(item) === ‘[object Array]’` なんて書いていたら、指が疲れてしまいますし、コードがごちゃごちゃして読みにくくなってしまいます。

そこで、現場のプロたちはこれを自分用の「便利ツール(関数)」に包んで使っています。一緒に作ってみましょう!

/

  • どんなデータでも、正確な型を小文字の文字列で返す優れものの関数
  • @param {any} value – 調べたいデータ
  • @returns {string} – “array”, “date”, “string” などの型名

/
function getExactType(value) {
// Object.prototype.toString.call(value) の結果から、
// “[object Array]” のような文字列の 8文字目から後ろを切り出して、小文字に変換する職人技です
const stringified = Object.prototype.toString.call(value);
const typeString = stringified.slice(8, -1).toLowerCase();

return typeString;
}

// さあ、使ってみましょう!
console.log(getExactType([1, 2, 3])); // “array”
console.log(getExactType(new Date())); // “date”
console.log(getExactType(/abc/)); // “regexp” (正規表現もわかる!)
console.log(getExactType(null)); // “null” (nullだって綺麗に判定できます)
console.log(getExactType(123)); // “number”

このようにラップ(包み隠す)してあげると、コードがスッキリして読みやすくなりますよね。

—

まとめ:型の迷子になったら、この呪文を思い出そう

Web制作やアプリケーション開発をしていると、予期せぬデータ形式に頭を悩ませることは日常茶飯事です。
「あれ、このデータなんでエラーになるんだろ?」と思ったときは、大抵が型の勘違いから起きています。

そんなときは、慌てず騒らず、今回お伝えした `Object.prototype.toString.call()` という鑑識官をそっと呼び出してみてください。きっと、データの本当の姿を優しく教えてくれますよ。

JavaScriptとの付き合いは長く続きます。分からないことが出てきても、「大丈夫、一つずつ紐解いていけば絶対に分かるようになる!」という気持ちで、一緒に楽しくコード書いていきましょうね!

コメント

タイトルとURLをコピーしました