prototypeとは
語源
製品開発を進めるうえで基本的な設計に問題がないかどうかを製品相当のテスト品を製造し、チェックしますが、プロトタイプとは、このときに製造されたプログラムの試作版のこと by Weblio辞書javaScriptにおける意味
プロトタイプは、JavaScript オブジェクトが互いに機能を継承するメカニズム by MDN書き方
まずはメソッドを持つオブジェクトを作る
let User = function(name, age) {
this.name = name;
this.age = age;
this.sayHi = function() {
return `Hi, I'm ${this.name}`;
};
}
let user = new User('John', 30);
console.log(user);
console.log(user.sayHi());
//コンソール
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
John
次にこれをprototypeを用いてつくる
※prototypeの書き方は
【 オブジェクト名.prototype.メソッド名= function() { } 】
let User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype.sayHi = function () {
return this.name
}
let user = new User('John', 30);
console.log(user);
console.log(user.sayHi());
//コンソール
{ name: 'John', age: 30 }
John
prototypeを使うメリット
2つの書き方の結果はほとんど同じである が一か所違うところが//コンソール
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
//コンソール
{ name: 'John', age: 30 }
上の例ではインスタンス化するときにメソッドもコピーするのに対し、
下の例では、コピーされていない
つまり、prototypeを使えば無駄なメモリの消費を抑えられる
prototypeはなぜメモリの消費を抑えられるのか
prototypeを用いるとインスタンス化の際メソッドは参照して、用いられるからである
例えば、例のコンストラクタをそれぞれ5回ずつインスタンス化した場合
//上の例
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
//下の例
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
prototype
(sayHiメソッド)
このようなイメージになる
インスタンス化が多いほどprotptypeを使うメリットが大きくなる
試しにprototypeの中を見てみると
let User = function(name, age) {
this.name = name;
this.age = age;
}
User.prototype.sayHi = function () {
return this.name
}
let user = new User('John', 30);
console.log(User.prototype.sayHi);
console.log(User.prototype.sayHi());
//コンソール
[Function (anonymous)]
undefined
メソッドである
console.log(User.prototype.sayHi());
がundefinedなのはインスタンス化していないのでthis.nameがundefinedのためである
「prototype」による継承
プロトタイプチェーン
中身が空のオブジェクトを3っつ用意しますlet soccerPlayer = function () { };
let baseballPlayer = function () { };
let doctor = function () { };
この3つのオブジェクトがそれぞれ持っている「プロトタイプ」を連結させるには
各プロトタイプには連結させたいオブジェクトのインスタンスを代入する
つまり
baseballPlayer.prototype = new soccerPlayer();
「baseballPlayer」と「soccerPlayer」のプロトタイプはそれぞれ参照できる状態である
そしてこうすることで
doctor.prototype = new baseballPlayer();
【soccerPlayer】【baseballPlayer】【doctor】
がそれぞれ繋がったわけでである
継承
let soccerPlayer = function () { };
let baseballPlayer = function () { };
soccerPlayer.prototype.kick = function () {
return 'kick';
}
baseballPlayer.prototype = new soccerPlayer();
let human1 = new soccerPlayer();
let human2 = new baseballPlayer();
console.log(human1.kick());
console.log(human2.kick());
//コンソール
kick
kick
baseballPlayerのprototypeはsoccerPlayerのprototypeを継承しているのでkickメソッドが使えるわけである