0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptのPrototypeとは?Prototype Chain・[[Prototype]]・__proto__を図解で理解する

0
Posted at

JavaScript(以後JSと書きます)を学習していく中で、Prototypeという言葉を目にすることがあると思います。
JSでは、オブジェクトの継承やメソッドの共有を実現する仕組みとしてPrototypeが採用されています。
今回、Prototypeについて学ぶ機会があったため、備忘録も兼ね初学者向けに記事を書いていこうと思います!

なぜPrototypeが必要なのか

下記コードを見てください。

const user1 = {
  name: "Taro",
  hello() {
    console.log("Hello");
  },
};

const user2 = {
  name: "Bob",
  hello() {
    console.log("Hello");
  },
};

user1、user2それぞれのオブジェクトでhelloメソッドがあります。
メソッドや変数はメモリ上に保持されます。
同じ内容のメソッドをオブジェクトごとに作成すると、その分だけメモリを消費してしまいます。
もし、user3、user4と増えていき、user1000となった場合、1000個のオブジェクトそれぞれに同じhello()メソッドが存在することになります。
JavaScriptでは、この問題を解決するための仕組みが用意されています!

それがPrototypeです!

Prototypeとは?

Prototypeを説明すると、「複数のオブジェクトで共通して利用するプロパティやメソッドをまとめて保持しておく場所」です。
すなわち、「共有場所のこと」ですね!
先ほどのhello()メソッドを、それぞれのオブジェクトが持つのではなく、Prototypeに1つだけ用意しておけば、すべてのオブジェクトから利用できます。

下記の図を見てください。

Prototypeの図1
ChatGPTで生成

この仕組みにより、helloメソッドは一つだけ作成され、複数のオブジェクトで共有できるため、メモリ効率が良くなります!

Prototype Chain

実際にPrototypeの使用例を見てみましょう!
次のようなオブジェクトがあるとします。

const user = {
  name: "Taro",
};

user.nameのようにプロパティへアクセスしたとき、JavaScriptはまずuserオブジェクト自身の中を探します。
見つからなかった場合、JavaScriptは、自動的にPrototypeの中を探しにいきます。
この「見つからなければPrototypeを順番に探していく仕組み」をPrototype Chain(プロトタイプチェーン)と呼びます。

下記は説明図です。
Prototype chainの図
ChatGPTで生成

下記のようにオブジェクト自体に存在しないメソッドが利用できるのもプロトタイプチェーンの仕組みのおかげです。

const user = {
  name: "Taro",
};

console.log(user.toString());//エラーにならない!

[[Prototype]]と__proto__って何?

[[Prototype]]とは

上の図の中にも度々登場した[[Prototype]]ですが、なんだこれはと思った方もいると思います。
実は、JavaScriptのすべてのオブジェクトは、内部に[[Prototype]]という特別な内部スロットを持っています。

内部スロット:開発者が直接操作できない、JavaScriptエンジンが内部で管理している情報のこと。

この[[Prototype]]には、「次に探しに行くオブジェクト」の参照が保存されています!

user
 ↓
[[Prototype]]
 ↓
Object.prototype

//こんな感じで、JavaScriptが自動で辿ります。

そのため、[[Prototype]]はJavaScriptエンジンだけが扱う内部スロットであり、通常のコードから直接アクセスすることはできません。

__proto__とは

もしかするとブラウザのコンソールで「__proto__」という表記を見たことがあるかもしれません!
__proto__は、内部スロットである[[Prototype]]を取得・設定するためにObject.prototypeに用意されているアクセサプロパティです!

アクセサプロパティ:値を直接保持するのではなく、取得(getter)や設定(setter)の処理を実行するためのプロパティです。

そのため、下記のようなコードで[[Prototype]]を取得できます!

console.log(user.__proto__);

//現在では下記を使うのが推奨されています。
Object.getPrototypeOf(user);

下記イメージ図です。

ChatGPTで生成

この__proto__ですが、オブジェクト自身は持っていません!
実は、Object.prototypeに定義されているアクセサプロパティです!

Object.prototype
│
├── toString()
├── hasOwnProperty()
└── __proto__ ← ここにある

こんな感じです!

user.__proto__を実行すると、内部的には次のような流れになります!

user.__proto__
  1. user自身に__proto__があるか探す
  2. 無い
  3. Object.prototypeへ移動
  4. __proto__アクセサを見つける
  5. そのアクセサがuserの[[Prototype]]を返す
    という流れになります。

実際に確認する方法として、「hasOwnProperty()」というオブジェクト自身がプロパティを持っているか確認するメソッドを実行すると「false」が返ってきます!

const user = {
  name: "Taro",
};

console.log(user.hasOwnProperty("__proto__"));
//falseが返ってくる!

hasOwnProperty()ではfalseになりますが、in演算子ではtrueになります!
これは、__proto__がuser自身ではなく、プロトタイプチェーン上のObject.prototypeに存在するためです。

console.log("__proto__" in user);
// true

つまり、user自身は__proto__を持っていません。
ここまでの違いをまとめると次のようになります。

項目 [[Prototype]] __proto__
全てのオブジェクトが持つか 持つ 直接持たない
種類 内部スロット アクセサプロパティ
JavaScriptから直接アクセス 不可 可能だが非推奨
説明 各オブジェクトが必ず持っている内部スロット。(JavaScriptエンジンだけが扱える) [[Prototype]]を取得・設定するためのプロパティ

まとめ

ここまでで、次の内容を解説しました。

用語 説明
Prototype 共通して利用するプロパティやメソッドを保持できるオブジェクト
Prototype Chain プロパティが見つからない場合にPrototypeを順番に探す仕組み
[[Prototype]] Prototype Chainをたどるために各オブジェクトが持つ内部スロット
__proto__ [[Prototype]]を取得・設定するためのアクセサプロパティ

JavaScriptでは、オブジェクト自身に存在しないプロパティやメソッドでも、プロトタイプチェーンをたどることで利用できる場合があります。

しかし、JavaScriptにはもう一つ紛らわしい名前があります。
それが「prototype」です。

prototypeは関数だけが持つ特別なプロパティで、new演算子やクラス構文を理解するうえで欠かせない存在です。

次回は、もう一つの重要な概念である prototype プロパティについて、クラスや new 演算子の仕組みと合わせて解説する予定です!」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?