「JavaScriptの基礎 - 継承とプロトタイプ」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

ページの作成:「== 概要 == JavaScriptはプロトタイプベースのオブジェクト指向言語であり、全ての継承はプロトタイプチェーンという仕組みによって実現されている。<br> ES2015で導入された <code>class</code> 構文の <code>extends</code> と <code>super</code> により、他の言語に近い直感的なクラス継承を記述できるが、<br> これはシンタックスシュガーである。(内部では依然とし…」
 
 
(同じ利用者による、間の3版が非表示)
4行目: 4行目:
これはシンタックスシュガーである。(内部では依然としてプロトタイプベースの機構が動作している)<br>
これはシンタックスシュガーである。(内部では依然としてプロトタイプベースの機構が動作している)<br>
<br>
<br>
プロトタイプチェーンとは、オブジェクトが持つ内部プロパティ <code>[[Prototype]]</code> を辿ることで、プロパティやメソッドを継承元から順に探索する仕組みである。<br>
プロトタイプチェーンとは、オブジェクトが持つ内部プロパティ <code><nowiki>[[Prototype]]</nowiki></code> を辿ることで、プロパティやメソッドを継承元から順に探索する仕組みである。<br>
プロパティは、<u>自身のオブジェクト -> プロトタイプ -> プロトタイプのプロトタイプ -> ... -> null</u> の順に探索され、見つからない場合は <u>undefined</u> を返す。<br>
プロパティは、<u>自身のオブジェクト -> プロトタイプ -> プロトタイプのプロトタイプ -> ... -> null</u> の順に探索され、見つからない場合は <u>undefined</u> を返す。<br>
<br>
<br>
137行目: 137行目:
<br>
<br>
==== プロトタイプの基本概念 ====
==== プロトタイプの基本概念 ====
全てのJavaScriptオブジェクトは、内部プロパティ <code>[[Prototype]]</code> を持つ。<br>
全てのJavaScriptオブジェクトは、内部プロパティ <code><nowiki>[[Prototype]]</nowiki></code> を持つ。<br>
この内部プロパティは、<code>Object.getPrototypeOf()</code> を使用して取得できる。<br>
この内部プロパティは、<code>Object.getPrototypeOf()</code> を使用して取得できる。<br>
<br>
<br>
164行目: 164行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
==== プロトタイプチェーンの仕組み ====
==== プロトタイプチェーンの仕組み ====
オブジェクトのプロパティやメソッドにアクセスすると、JavaScriptエンジンは以下の順序で探索を行う。<br>
オブジェクトのプロパティやメソッドにアクセスすると、JavaScriptエンジンは以下の順序で探索を行う。<br>
<br>
<br>
# オブジェクト自身のプロパティを探索する。
# オブジェクト自身のプロパティを探索する。
# 見つからない場合、<code>[[Prototype]]</code> (プロトタイプ) のプロパティを探索する。
# 見つからない場合、<code><nowiki>[[Prototype]]</nowiki></code> (プロトタイプ) のプロパティを探索する。
# 見つからない場合、プロトタイプのプロトタイプを探索する。
# 見つからない場合、プロトタイプのプロトタイプを探索する。
# <code>null</code> に到達しても見つからない場合、<u>undefined</u> を返す。
# <code>null</code> に到達しても見つからない場合、<u>undefined</u> を返す。
202行目: 203行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
==== classとプロトタイプの関係 ====
==== classとプロトタイプの関係 ====
<code>class</code> 構文はシンタックスシュガーであり、内部的にはプロトタイプベースの継承を使用している。<br>
<code>class</code> 構文はシンタックスシュガーであり、内部的にはプロトタイプベースの継承を使用している。<br>
249行目: 251行目:
! class構文 !! プロトタイプベースの等価コード !! 説明
! class構文 !! プロトタイプベースの等価コード !! 説明
|-
|-
| <u>class Animal {}</u> || <u>function Animal() {}</u> || クラス宣言はコンストラクタ関数に対応する
| class Animal {} || function Animal() {} || クラス宣言はコンストラクタ関数に対応する。
|-
|-
| <u>constructor(name) { this.name = name; }</u> || <u>function Animal(name) { this.name = name; }</u> || コンストラクタ本体はそのまま関数本体になる
| constructor(name) { this.name = name; } || function Animal(name) { this.name = name; } || コンストラクタ本体はそのまま関数本体になる。
|-
|-
| <u>speak() { ... }</u> || <u>Animal.prototype.speak = function() { ... };</u> || インスタンスメソッドはprototypeに追加される
| speak() { ... } || Animal.prototype.speak = function() { ... }; || インスタンスメソッドは <u>prototype</u> に追加される。
|-
|-
| <u>static create() { ... }</u> || <u>Animal.create = function() { ... };</u> || 静的メソッドはコンストラクタ関数自体のプロパティになる
| static create() { ... } || Animal.create = function() { ... }; || 静的メソッドはコンストラクタ関数自体のプロパティになる。
|-
|-
| <u>class Dog extends Animal</u> || <u>Object.setPrototypeOf(Dog.prototype, Animal.prototype);</u> || extendsはプロトタイプチェーンを設定する
| class Dog extends Animal || Object.setPrototypeOf(Dog.prototype, Animal.prototype); || <u>extends</u> はプロトタイプチェーンを設定する。
|-
|-
| <u>super(name)</u> || <u>Animal.call(this, name);</u> || super()は親コンストラクタをthisに対して呼び出す
| super(name) || Animal.call(this, name); || <u>super()</u> は親コンストラクタを <u>this</u> に対して呼び出す。
|-
|-
| <u>super.speak()</u> || <u>Animal.prototype.speak.call(this);</u> || super.method()は親のprototypeのメソッドを呼び出す
| super.speak() || Animal.prototype.speak.call(this); || <u>super.method()</u> は親の <u>prototype</u> のメソッドを呼び出す。
|}
|}
</center>
</center>