こんにちは!フロントエンドの現場を渡り歩いているチーフアーキテクトの私です。
JavaScriptを触り始めてすぐの頃、誰もが一度は「おや?」と首をかしげる不思議な現象に遭遇します。それが今回お話しする「関数はオブジェクトなのに、`typeof`で調べるとなぜか`’function’`という専用の答えが返ってくる問題」です。
「オブジェクトの一種なんでしょ?じゃあ`’object’`って返してよ!」って思いますよね。すごくわかります。私も駆け出しの頃、この仕様の裏側を知って「JavaScriptってなんて気まぐれなんだ……」と遠い目をしたものです。
でも、大丈夫ですよ。この仕様には、JavaScriptという言語が生まれた歴史的な背景と、私たちプログラマへの「ちょっとした優しい配慮」がちゃーんと隠されています。今日はそのモヤモヤを、身近な例えを交えながらスッキリ解消していきましょう!
—
そもそも `typeof` 演算子ってなに?
JavaScriptにおける `typeof` は、目の前にあるデータが「いったい何の種類のデータなのか」をサクッと教えてくれる便利なラベル貼り機のようなものです。
例えば、お買い物のレジを思い浮かべてみてください。目の前に流れてきた商品が「リンゴ(文字列)」なのか、「個数(数値)」なのか、「会員証(オブジェクト)」なのかをパッと見極める必要がありますよね。`typeof` は、まさにその値の正体を文字で教えてくれる頼もしい相棒です。
// 身の回りのデータを typeof で調べてみましょう
console.log(typeof “こんにちは”); // 结果: “string” (文字列だよ)
console.log(typeof 42); // 结果: “number” (数字だよ)
console.log(typeof true); // 结果: “boolean” (真偽値だよ)
ここまでは「うんうん、分かりやすい!」とスムーズに理解できます。問題は、ここから「関数(function)」が登場したときです。
—
関数は「お仕事ができるスーパー・オブジェクト」
JavaScriptの世界では、「関数もオブジェクトの一種」という大原則があります。
「えっ、関数ってコードの塊じゃないの?」と思われるかもしれませんが、JavaScriptの関数はただの命令文の束ではなく、中に「プロパティ」を持たせたり、別の変数に入れたりできる、いわば「お仕事ができる万能なオブジェクト」なんです。
身近な例えで言うと、関数は「リモコン」のようなものです。
リモコン(関数)それ自体はプラスチックの塊(オブジェクト)ですが、ボタンを押すことでテレビをつけたり(処理を実行したり)、裏側に電池(プロパティ)を隠し持ったりできますよね。
だから、厳密に言えば、関数はオブジェクトの親戚、いや、オブジェクトそのものなんです。
—
なぜ `typeof` は「object」ではなく「function」と答えるのか?
さて、ここからが本題です。
関数がオブジェクトの一種なのだから、`typeof` で調べたら当然 `”object”` と返ってくるはず……と思いきや、JavaScriptはこう答えます。
function sayHello() {
console.log(“こんにちは!”);
}
console.log(typeof sayHello); // 结果: “function” (えっ、”object”じゃないの!?)
「あれ?嘘つき!」って思いませんでしたか?
実はこれ、エラーでも気まぐれでもなく、「関数であることを見分けやすくしてあげるための、言語設計者たちの優しさ(配慮)」なんです。
もし、もしもですよ。もし JavaScript が仕様通りに、関数に対しても `typeof` の結果を単なる `\”object\”` にしてしまった世界を想像してみてください。
プログラムの中で「あ、これはデータを格納する箱(普通のオブジェクト)だな」と判断して処理を書いていたつもりが、実は「今すぐ実行できる関数」だったり、その逆だったりした場合、区別をつけるのがものすごく大変になりますよね。
「オブジェクト」という大きすぎる括りの中から、「これは動かせる関数(アクションを起こせるもの)だよ!」と一目でわかるように、専用のラベル(`”function”`)を貼って特別扱いしてあげよう。そうすることで、私たちプログラマがコードを書くときに迷いにくくしたのです。
歴史的にはJavaScriptの初期のバグや仕様の名残とも言われますが、実務をこなす今の私たちからすると、「お陰で関数と普通のオブジェクトをパッと見分けられて助かってます!」と感謝したくなるナイスな仕様なんですよ。
—
実務で役立つ!「関数もオブジェクト」を実感するコード
「関数がオブジェクトの一種」という言葉に納得していただくために、ちょっと面白いコードをお見せしますね。
実は、関数にはプロパティ(おまけのデータ)を後からくっつけることができます。これは普通のオブジェクトと同じ挙動です。
// 普通の関数を定義します
function greet() {
return “やあ!”;
}
// なんと、関数に関数自体のプロパティを後から生やすことができます!
greet.author = “JavaScriptの匠”;
greet.version = 1.0;
// プロパティにアクセスしてみる
console.log(greet()); // 结果: “やあ!” (通常通り関数として動く)
console.log(greet.author); // 结果: “JavaScriptの匠” (オブジェクトのように値を持てる!)
console.log(typeof greet); // 结果: “function” (でもtypeofはちゃんと”function”と答える)
このように、関数は「実行できる」という特別な能力を持っていながら、中身はちゃっかりオブジェクトとしての性質も持ち合わせている二面性のスターなんです。
—
まとめ:つまずきやすいポイントを優しく包み込んで
今回のテーマをギュッと凝縮して振り返ってみましょう。
1. 関数は実質的にオブジェクトの一種である。(オブジェクトの仲間)
2. でも `typeof` 演算子は、私たち開発者が区別しやすくするために、あえて `”function”` という専用のラベルを返してくれる。
3. この仕様のおかげで、私たちは「動かせるコードの塊」と「データをまとめる箱」をスッキリ見分けることができる。
JavaScriptの世界には、こうした「歴史の積み重ねによるちょっとした例外や優しさ」がたくさん散らばっています。最初は「なんでやねん!」と突っ込みたくなることも多いですが、その背景にある理由を知るたびに、この言語のことが少しずつ好きになっていくはずです。
もしまた分からない仕様に出会ったら、「あ、またJavaScriptが何か気を利かせてくれているんだな」と肩の力を抜いて、そっと向き合ってみてくださいね。
あなたのフロントエンド開発の旅が、これからも楽しくワクワクするものでありますように!チーフアーキテクトの私でした。

コメント