JavaScriptプロトタイプ解説
JavaScriptにおける.prototype
と.__proto__
の違い
.prototype
と.__proto__
は、JavaScriptにおけるオブジェクトのプロトタイプチェーンに関する重要な概念です。どちらもプロトタイプ継承に関わるものですが、その役割と使用方法が異なります。
.prototype
- コンストラクタ関数による使用
多くの場合、コンストラクタ関数を使用してオブジェクトを作成するとき、そのコンストラクタ関数の.prototype
プロパティがオブジェクトの親オブジェクトとなります。 - プロパティとメソッドの定義
.prototype
オブジェクトに定義されたプロパティやメソッドは、そのオブジェクトのすべてのインスタンスに継承されます。 - オブジェクトのプロトタイプ
あるオブジェクトの親オブジェクト、またはテンプレートとなるオブジェクトです。
例
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
console.log("Hello, my name is " + this.name);
};
const john = new Person("John ", 30);
john.greet(); // Output: Hello, my name is John
.__proto__
- オブジェクトの継承
オブジェクトがアクセスできないプロパティやメソッドを検索するとき、.__proto__
プロパティを使用してプロトタイプチェーンを辿り、そのプロパティやメソッドが存在するオブジェクトを探します。 - プロトタイプチェーンのリンク
.__proto__
プロパティは、オブジェクトのプロトタイプチェーンを辿るためのリンクとして機能します。 - 個々のオブジェクトのプロトタイプ
あるオブジェクトの親オブジェクトへの参照です。
const john = new Person("John", 30);
console.log(john.__proto__ === Person.prototype); // Output: true
.__proto__
は、個々のオブジェクトのプロトタイプへの参照であり、プロトタイプチェーンを辿るためのリンクとして機能します。.prototype
は、コンストラクタ関数に関連付けられたプロトタイプオブジェクトであり、そのオブジェクトのすべてのインスタンスに継承されます。
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person.prototypeにgreetメソッドを追加
Person.prototype.greet = function() {
console.log("Hello, my name is " + this.name);
};
// Personオブジェクトのインスタンスを作成
const john = new Person("John", 30);
// johnオブジェクトはgreetメソッドを継承している
john.greet(); // Output: Hello, my name is John
- インスタンスへの継承
john
オブジェクトはPersonコンストラクタ関数のインスタンスなので、greet
メソッドを継承しています。そのため、john.greet()
を実行すると、greet
メソッドが呼び出され、"Hello, my name is John"が出力されます。 - .prototypeの役割
Personコンストラクタ関数の.prototype
プロパティにgreet
メソッドを追加しています。これにより、Personオブジェクトのすべてのインスタンスがgreet
メソッドを継承します。
const john = new Person("John", 30);
// johnオブジェクトの__proto__プロパティはPerson.prototypeを参照している
console.log(john.__proto__ === Person.prototype); // Output: true
- プロトタイプチェーン
john
オブジェクトがgreet
メソッドを呼び出すとき、まず自身のプロパティにgreet
メソッドが存在するかチェックします。存在しない場合、.__proto__
プロパティを使用してプロトタイプチェーンを辿り、greet
メソッドが存在するオブジェクトを探します。この場合、Person.prototypeにgreet
メソッドが存在するため、それが呼び出されます。 - .__proto__の役割
john
オブジェクトの.__proto__
プロパティは、そのオブジェクトのプロトタイプへの参照です。この場合、john
オブジェクトのプロトタイプはPerson.prototypeです。
クラス構文 (ES6以降)
- インスタンスの作成
new
キーワードを使用してクラスのインスタンスを作成します。 - プロパティとメソッドの定義
クラス内部でプロパティとメソッドを定義します。 - クラスの定義
class
キーワードを使用してクラスを定義します。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log("Hello, my name is " + this.name);
}
}
const john = new Person("John", 30);
john.gre et(); // Output: Hello, my name is John
Object.create()
- オブジェクトの作成
Object.create()
メソッドを使用して、指定したプロトタイプオブジェクトを持つ新しいオブジェクトを作成します。
const personPrototype = {
greet() {
console.log("Hello, my name is " + this.name);
}
};
const john = Object.create(personPrototype);
john.name = "John";
john.greet(); // Output: Hello, my name is John
プロトタイプチェーンの操作ライブラリ
- ライブラリの使用
lodash
やunderscore
などのライブラリには、プロトタイプチェーンを操作するためのメソッドが提供されています。
const _ = require('lodash');
const personPrototype = {
greet() {
console.log("Hello, my name is " + this.name);
}
};
const john = _.extend({}, personPrototype);
john.name = "John";
john.greet(); // Output: Hello, my name is John
ミックスイン
- 複数のオブジェクトの結合
ミックスインを使用して、複数のオブジェクトのプロパティやメソッドを1つのオブジェクトに結合します。
function mixin(target, ...sources) {
sources.forEach(source => {
for (const key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
});
return target;
}
const person = {
name: "John"
};
const greeter = {
greet() {
console.log("Hello, my name is " + this.name);
}
};
const john = mixin({}, person, greeter);
john.greet(); // Output: Hello, my name is John
javascript prototype javascript-objects