導入
プロトタイプとは、JavaScript オブジェクトが互いにプロパティを継承するメカニズムです。この記事では、プロトタイプとは何か、プロトタイプチェーンの仕組み、そしてオブジェクトのプロトタイプを設定する方法について説明します。.
前提条件
JavaScript の機能を理解し、JavaScript の基礎 (「はじめに」と「ビルディング ブロック」を参照) と OOJS の原則 (「オブジェクトの概要」を参照) に慣れてください。.
プロトタイプチェーン
ブラウザ コンソールで、リテラル オブジェクトを作成してみます。
const myObject = {
city: "Madrid",
greet() {
console.log(`Greetings from ${this.city}`);
},
};
myObject.greet(); // Greetings from Madridこれは、データプロパティ「city」とメソッド「greet()」を持つオブジェクトです。コンソールにオブジェクト名の後にピリオド(「myObject.」のように)を入力すると、このオブジェクトで利用可能なすべてのプロパティのリストが表示されます。「city」と「greeting」以外にも、たくさんのプロパティがあることがわかります。
__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
valueOf次のいずれかにアクセスしてみてください:
myObject.toString(); // "[object Object]"
これは動作します (toString() が何をするのか明確でない場合でも)。.
これらの追加プロパティとは何ですか? また、どこから来るのでしょうか?
JavaScript のすべてのオブジェクトには、プロトタイプと呼ばれる組み込みプロパティがあります。プロトタイプはそれ自体がオブジェクトであるため、プロトタイプはそれぞれ独自のプロトタイプを持ち、プロトタイプチェーンと呼ばれるものを形成します。このチェーンは、プロトタイプが null であるプロトタイプに到達した時点で終了します。.
注: オブジェクトのプロトタイプを指すプロパティは、プロトタイプとは呼ばれません。この名称は標準ではありませんが、実際にはすべてのブラウザで __proto__ が使用されています。オブジェクトのプロトタイプにアクセスする標準的な方法は、Object.getPrototypeOf() メソッドです。.
オブジェクトのプロパティにアクセスしようとすると、オブジェクト自体にプロパティが見つからない場合、そのプロパティのプロトタイプが検索されます。それでもプロパティが見つからない場合は、インスタンスのプロトタイプが検索され、プロパティが見つかるかチェーンの終端に達するまでこの処理が続けられます。終端に達した場合は、undefined が返されます。.
したがって、myObject.toString() を呼び出すと、ブラウザは次の処理を実行します。
- myObject 内の toString を検索します
- そこには見つからないので、myObjectオブジェクトのプロトタイプでtoStringを検索します。
- 彼はそれをそこで見つけて、電話をかけます。.
myObject のプロトタイプは何でしょうか?それを調べるには、Object.getPrototypeOf() 関数を使います。
Object.getPrototypeOf(myObject); // Object { }
これはObject.prototypeと呼ばれるオブジェクトで、すべてのオブジェクトがデフォルトで持つ最も基本的なプロトタイプです。Object.prototypeプロトタイプはnullなので、プロトタイプチェーンの最後尾に位置します。
オブジェクトのプロトタイプは必ずしもObject.prototypeとは限りません。次の例を試してみてください。
const myDate = new Date();
let object = myDate;
do {
object = Object.getPrototypeOf(object);
console.log(object);
} while (object);
// Date.prototype
// Object { }
// nullこのコードは Date オブジェクトを作成し、プロトタイプチェーンを遡ってプロトタイプを登録します。myDate のプロトタイプは Date.prototype オブジェクトであり、そのプロトタイプは Object.prototype であることがわかります。.
実際、myDate2.getTime() などの使い慣れたメソッドを呼び出すときは、Date.prototype で定義されたメソッドを呼び出しています。.
シェーディングプロパティ
オブジェクトのプロトタイプに同じ名前のプロパティが定義されている場合、オブジェクトにプロパティを定義するとどうなるでしょうか? ちょっと考えてみましょう。
const myDate = new Date(1995, 11, 17);
console.log(myDate.getTime()); // 819129600000
myDate.getTime = function () {
console.log("something else!");
};
myDate.getTime(); // 'something else!'プロトタイプチェーンの記述から、これは予測可能なはずです。getTime() を呼び出すと、ブラウザはまず myDate 内でその名前のプロパティを探し、myDate にそのプロパティが定義されていない場合のみプロトタイプをチェックします。つまり、myDate に getTime() を追加すると、myDate 内のバージョンが呼び出されます。.
これはプロパティの「シャドウイング」と呼ばれます。.
プロトタイプの設定
JavaScript でオブジェクトのプロトタイプを設定する方法はいくつかありますが、ここでは Object.create() とコンストラクターの 2 つについて説明します。.
Object.create の使用
Object.create() メソッドは新しいオブジェクトを作成し、新しいオブジェクトのプロトタイプとして使用するオブジェクトを指定できるようにします。.
次に例を示します。
const personPrototype = {
greet() {
console.log("hello!");
},
};
const carl = Object.create(personPrototype);
carl.greet(); // hello!ここでは、 greet() メソッドを持つ personPrototype オブジェクトを作成します。次に、Object.create() を使用して、 personPrototype をプロトタイプとする新しいオブジェクトを作成します。これで、新しいオブジェクトに対して greet() を呼び出すことができ、プロトタイプがその実装を提供します。.
コンストラクタの使用
JavaScriptでは、すべての関数にprototypeというプロパティがあります。関数をコンストラクターとして呼び出すと、このプロパティは新しく作成されたオブジェクトのプロトタイプ(慣例的に__proto__というプロパティ)に設定されます。.
したがって、コンストラクタのプロトタイプを設定すると、そのコンストラクタで作成されたすべてのオブジェクトにそのプロトタイプが付与されることを保証できます。
const personPrototype = {
greet() {
console.log(`hello, my name is ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// or
// Person.prototype.greet = personPrototype.greet;ここで作成するのは以下です:
- greet() メソッドを持つ personPrototype オブジェクト
- 作成する人物の名前を初期化する Person() コンストラクター関数。.
次に、Object.assign を使用して、personPrototype で定義されたメソッドを Person 関数の prototype プロパティに配置します。.
このコードの後、Person.prototype() を使用して作成されたオブジェクトはプロトタイプとして を受け取り、これには greet メソッドが自動的に含まれます。.
const reuben = new Person("Reuben");
reuben.greet(); // hello, my name is Reuben!これは、myDate のプロトタイプが Date.prototype と呼ばれると先ほど述べた理由も説明しています。これは、Date コンストラクターのプロトタイプ プロパティです。.
所有財産
上記の Person コンストラクターを使用して作成するオブジェクトには、次の 2 つのプロパティがあります。
- コンストラクタで設定される名前プロパティ。Person オブジェクトに直接表示されます。
- プロトタイプに設定された greet() メソッド。.
メソッドはプロトタイプで定義され、データプロパティはコンストラクタで定義されるというパターンはよく見られます。これは、メソッドは通常、作成するすべてのオブジェクトで同じである一方、データプロパティは各オブジェクトごとに固有の値を持つようにしたい場合が多いためです(この例では、人の名前がそれぞれ異なります)。.
ここでの名前のように、オブジェクトに直接定義されたプロパティは、独自のプロパティと呼ばれ、静的な Object.hasOwn() メソッドを使用して、プロパティが特定のプロパティであるかどうかを確認できます。
const irma = new Person("Irma");
console.log(Object.hasOwn(irma, "name")); // true
console.log(Object.hasOwn(irma, "greet")); // false注: ここでは非静的な Object.hasOwnProperty() メソッドを使用することもできますが、可能な場合は Object.hasOwn() を使用することをお勧めします。.
プロトタイプと継承
プロトタイプは、コードの再利用とオブジェクトの構成を可能にする強力で柔軟性の高い JavaScript 機能です。.
これらは継承の特定のバージョンを具体的にサポートしています。継承はオブジェクト指向プログラミング言語の機能であり、プログラマーがシステム内の一部のオブジェクトが他のオブジェクトのより特殊化されたバージョンであるという考えを表現できるようにします。.
例えば、学校をモデル化するとすると、教師と生徒がいるとします。どちらも人間なので、いくつかのプロパティ(例:名前を持つ)を共有しますが、それぞれが追加のプロパティ(例:教師には教える科目がある)を持つ場合や、同じプロパティを異なる方法で実装する場合があります。OOPシステムでは、教師と生徒はどちらもPeopleから継承すると言えるでしょう。.
JavaScript では、Professor オブジェクトと Student オブジェクトが Person プロトタイプを持つことができれば、共通のプロパティを継承しながら、異なる必要があるプロパティを追加および再定義できることがわかります。.
次の記事では、継承とオブジェクト指向プログラミング言語の他のコア機能について説明し、JavaScript がそれらをどのようにサポートしているかを見ていきます。.
結果
この記事では、オブジェクト プロトタイプ チェーンによってオブジェクトが相互にプロパティを継承できるようにする方法、プロトタイプ プロパティとそれを使用してコンストラクターにメソッドを追加する方法、およびその他の関連トピックなど、JavaScript オブジェクト プロトタイプについて説明します。.









