なぜJavaScriptの全てはオブジェクトなのか
記事にしようかなと思っていることの下書き。
タイトルは仮で入れているが主題としてはJavaScriptにおいてプリミティブ型として扱われているものも実際はオブジェクトであることを説明する。
対象読者としてはJavaScriptがある程度分かっている人として
- JavaScriptやNode.jsなどである程度自分で機能を作れる人
- JavaScriptの型について一通りの知識が入っている人
上記を前提とする。
内容がちょっと複雑なので初学者が見てしまうと余計混乱するおそれがあるのでなるべくJavascriptを書きなれてきた人向けの内容であることを最初に記載しておく。
まずは下記のコードを見てほしい。
const str = 'hoge';
const upperHoge = str.toUpperCase();
console.log(upperHoge); // 'HOGE'
このコードでは変数str
に'hoge'
というstring
型の値を代入してその後
変数str
からtoUpperCase()
というメソッドを呼び出してその返り値を変数upperHoge
に代入した後コンソールに出力している。
何の変哲もないコードであり、コードとしての間違えなどはなく正しく動くが、よくよく考えるとおかしな部分がある。
まずは変数str
の宣言箇所ではプリミティブな値であるstring型の値を代入している。
しかし次の変数upperHoge
の宣言箇所ではstr
からtoUpperCase()
というメソッドを呼び出している。
先程述べたおかしな部分というのはこのメソッド呼び出しの部分である。
MDNのプリミティブ型の説明にはこうある。
JavaScript において、プリミティブ (primitive、プリミティブ値、プリミティブデータ型) はオブジェクトでなく、メソッドを持たないデータのことです。 6 種類のプリミティブデータ型があります。文字列、数値、BigInt、真偽値、undefined、そしてシンボル (ECMAScript 2016 で追加) です。
「オブジェクトでなく、メソッドを持たないデータのことです。」とあるのにメソッドを呼び出しているのである。
例えば下記のように値の定義と同時にメソッドの定義を行ったオブジェクトを宣言したというのであればメソッドの呼び出しができるのは納得できる。
const o = {
value: 'piyo',
method: function() {
return this.value + this.value
}
};
console.log(o.value); // 'piyo'
console.log(o.method()); // 'piyopiyo'
プリミティブな値であってもオブジェクトのように各種プロパティやメソッドにアクセス可能であるという点を理解するとString
クラスがあってそれをnew String()
のように初期化したものを変数に代入しているのではないかと考える人も多いと思う。
これも考え方としては近いが厳密に言うと間違っている。
変数に入れられる値は'hoge'
という値を入れたら'hoge'
という値以外は何も入っていないプリミティブな値であるが、それを呼び出すときに自動的に対応したラッパーオブジェクトに変換されているという表現が正しい。
試しにコンソールなどで下記の2つの変数を表示してみると違う結果が返ってくるのがわかる。
const primitive = 'hoge';
const instance = new String('hoge');
console.log(primitive); // hoge // 文字列として表示される
console.log(instance); // String {'hoge'} // Stringオブジェクトとして表示される
console.log(primitive === instance); // false
上記の厳密な定義については少し難しい概念になってしまうが、Javascriptのデータを操作する立場から見るとnull
とundefined
を除くと純粋にプリミティブな値というのは存在せずすべてをオブジェクトとして扱っていると言える。
これを理解すると何が嬉しいのか
そこまで理解しても意味はないと思う。
プリミティブな値であってもプロパティやメソッドにアクセスできるというのは感覚的にみんな理解している部分ではあるし、これを理解したからといって直接的になにかコードの書き方が変わるとかクオリティがあがるとかそういうわけではないと思う。
ただ、こういった基礎的な部分の学習を行わずに表面的な知識をつけても最終的には点と点がつながるような理解が発生する機会が少なく非効率な学習になると個人的には思っています。