Closed4

なぜJavaScriptの全てはオブジェクトなのか

ken7253ken7253

記事にしようかなと思っていることの下書き。
タイトルは仮で入れているが主題としてはJavaScriptにおいてプリミティブ型として扱われているものも実際はオブジェクトであることを説明する。

対象読者としてはJavaScriptがある程度分かっている人として

  • JavaScriptやNode.jsなどである程度自分で機能を作れる人
  • JavaScriptの型について一通りの知識が入っている人

上記を前提とする。

内容がちょっと複雑なので初学者が見てしまうと余計混乱するおそれがあるのでなるべくJavascriptを書きなれてきた人向けの内容であることを最初に記載しておく。

ken7253ken7253

まずは下記のコードを見てほしい。

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 で追加) です。

https://developer.mozilla.org/ja/docs/Glossary/Primitive

「オブジェクトでなく、メソッドを持たないデータのことです。」とあるのにメソッドを呼び出しているのである。

例えば下記のように値の定義と同時にメソッドの定義を行ったオブジェクトを宣言したというのであればメソッドの呼び出しができるのは納得できる。

const o = {
    value: 'piyo',
    method: function() {
      return this.value + this.value
  }
};

console.log(o.value); // 'piyo'
console.log(o.method()); // 'piyopiyo'
ken7253ken7253

プリミティブな値であってもオブジェクトのように各種プロパティやメソッドにアクセス可能であるという点を理解すると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のデータを操作する立場から見るとnullundefinedを除くと純粋にプリミティブな値というのは存在せずすべてをオブジェクトとして扱っていると言える。

ken7253ken7253

これを理解すると何が嬉しいのか

そこまで理解しても意味はないと思う。
プリミティブな値であってもプロパティやメソッドにアクセスできるというのは感覚的にみんな理解している部分ではあるし、これを理解したからといって直接的になにかコードの書き方が変わるとかクオリティがあがるとかそういうわけではないと思う。
ただ、こういった基礎的な部分の学習を行わずに表面的な知識をつけても最終的には点と点がつながるような理解が発生する機会が少なく非効率な学習になると個人的には思っています。

このスクラップは2023/02/01にクローズされました