1 2 3 4 5 6 |
function Car() { this.color = 'red'; this.drive = function() { console.log("drive"); } } |
1 2 3 4 5 6 |
function Car2() { this.color = 'red'; } Car2.prototype.drive = function() { console.log("drive"); } |
Carというコンストラクタ関数に、drive()というメソッドを追加する場合、上記のように2つのやり方があります。
- 前者のコンストラクタ関数のプロパティとして関数を追加する方法
- 後者のコンストラクタ関数をprototype拡張して追加する方法
基本的に汎用的なメソッドを追加する場合は、後者のprototype拡張を利用したほうが良いです。
Prototype拡張を利用したほうが良い理由
メソッドを追加するときに、コンストラクタ関数のプロパティとして追加するよりも、prototype拡張を利用したほうが良い理由はメモリの節約です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function Car() { this.color = 'red'; this.drive = function() { console.log("drive"); } } const carInstance1 = new Car(); const carInstance2 = new Car(); console.log(carInstance1); // Car { color: 'red', drive: [Function] } console.log(carInstance2); // Car { color: 'red', drive: [Function] } carInstance1.drive(); // drive carInstance2.drive(); // drive |
このように、コンストラクタ関数のプロパティとして、メソッドを追加すると、全てのインスタンスのプロパティとしてdrive()メソッドを持ちます。
一方、prototype拡張を利用した場合、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function Car2() { this.color = 'red'; } Car2.prototype.drive = function() { console.log("drive"); } const car2Instance1 = new Car2(); const car2Instance2 = new Car2(); console.log(car2Instance1); // Car2 { color: 'red' } console.log(car2Instance2); // Car2 { color: 'red' } car2Instance1.drive(); // drive car2Instance2.drive(); // drive |
このように、インスタンス化した変数の中にはdriveメソッドを持つことがなく、drive()メソッドを実行したタイミングで、prototypeからdrive()メソッドを呼び出します。
パフォーマンス向上のためにも、prototype拡張がオススメ
javascriptの場合、オブジェクトがプロパティを保持していなかった場合、prototypeにそのプロパティがないかを探しに行くため、prototype拡張を利用しておけば、メモリを無駄に消費せずに、必要なとき(実行時)のみ処理を走らせることができます!