__proto__とprototypeの違い
JavaScriptにおける proto と prototype の詳細比較
proto とは?
proto は、オブジェクトのプロトタイプチェーンの次のオブジェクトへの直接参照です。つまり、あるオブジェクトがプロパティやメソッドにアクセスできない場合、proto によって参照される別のオブジェクトから継承しようとする仕組みです。
例:
function Person(name) {
this.name = name;
}
const person = new Person('Alice');
console.log(person.__proto__); // { name: 'Alice', constructor: Person }
この例では、person.__proto__
は Person.prototype
を参照します。つまり、person
オブジェクトは name
プロパティと constructor
プロパティを Person.prototype
から継承していることを意味します。
prototype は、コンストラクター関数によって作成されたすべてのオブジェクトが継承するプロパティとメソッドのセットを定義するオブジェクトです。つまり、prototype は、そのコンストラクターで生成されたすべてのオブジェクトのプロトタイプチェーンの最上位に位置します。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person = new Person('Alice');
person.greet(); // Hello, my name is Alice
この例では、Person.prototype
に greet
メソッドが定義されています。person
オブジェクトは greet
メソッドを直接持っていませんが、prototype チェーンを辿ることで Person.prototype
から継承し、greet
メソッドを呼び出すことができます。
proto と prototype の違い
項目 | proto | prototype |
---|---|---|
定義 | オブジェクトのプロトタイプチェーンの次のオブジェクトへの直接参照 | コンストラクター関数によって作成されたすべてのオブジェクトが継承するプロパティとメソッドのセットを定義するオブジェクト |
アクセス方法 | オブジェクトインスタンスに対して __proto__ プロパティでアクセス | コンストラクター関数に対して .prototype プロパティでアクセス |
変更可能性 | 個々のオブジェクトインスタンスに対して変更可能 | コンストラクター関数に対してのみ変更可能 |
継承 | 個々のオブジェクトインスタンスに対して継承 | コンストラクターで生成されたすべてのオブジェクトに対して継承 |
- proto は個々のオブジェクトのプロトタイプチェーンにおける次のオブジェクトへの参照であり、変更可能です。
補足
- 新しい JavaScript エンジンでは、proto は非推奨となり、代わりに
Object.getPrototypeOf()
とObject.setPrototypeOf()
メソッドを使用することが推奨されています。
JavaScriptにおける proto と prototype の理解を深めるためのサンプルコード
基本的な動作
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person = new Person('Alice');
console.log(person.__proto__); // { name: 'Alice', constructor: Person }
console.log(Person.prototype); // { constructor: Person, greet: ƒ }
person.greet(); // Hello, my name is Alice
解説:
- このコードでは、
Person
コンストラクター関数と、そのprototype
オブジェクトにgreet
メソッドを定義しています。 person
インスタンスはPerson.prototype
からgreet
メソッドを継承し、呼び出すことができます。person.__proto__
はPerson.prototype
を参照していることを確認できます。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person = new Person('Alice');
person.__proto__ = {
greet: function() {
console.log('Hi there!');
}
};
person.greet(); // Hi there!
- このコードでは、
person
インスタンスの__proto__
を別のオブジェクトに変更しています。 - その結果、
person.greet
は元のPerson.prototype.greet
ではなく、新しく設定されたメソッドが呼び出されます。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person = new Person('Alice');
Person.prototype.greet = function() {
console.log('Hello, everyone!');
};
person.greet(); // Hello, everyone!
- このコードでは、
Person.prototype.greet
メソッドを直接変更しています。 - その結果、
person
インスタンスを含む、そのコンストラクターで生成されたすべてのオブジェクト のgreet
メソッドが変更されます。
Object.create() を使ったオブジェクトの作成
const personProto = {
greet: function() {
console.log('Hello from prototype!');
}
};
const person = Object.create(personProto);
person.name = 'Alice';
console.log(person.__proto__); // { greet: ƒ }
console.log(person.greet()); // Hello from prototype!
- このコードでは、
Object.create()
メソッドを使って、personProto
オブジェクトをプロトタイプとするperson
オブジェクトを作成しています。 person
オブジェクトはgreet
メソッドをpersonProto
から継承し、呼び出すことができます。
ビジュアルツール
これらのツールは、オブジェクトのプロトタイプチェーンと、proto と prototype がどのように関係しているのかを視覚的に表現することができます。
インタラクティブなチュートリアル
これらのチュートリアルは、proto と prototype の基本的な概念から、より高度な使用方法まで、段階的に学ぶことができます。
これらの書籍は、proto と prototype の理論的な説明だけでなく、実際のコード例も豊富に掲載されています。
これらのフォーラムやコミュニティには、proto と prototype に関する豊富な情報と、経験豊富な開発者からの回答が揃っています。
javascript prototype javascript-objects