その1 - そもそもオブジェクトとはなんぞ
その2 - "コンストラクタ"を使うと類似オブジェクトを作るのが便利
その3 - "プロトタイプ"を使うとオブジェクト作成が合理的になる
番外編 - クラスの概念に縛られた巷のオブジェクト指向の説明
JavaScriptでオブジェクト指向を理解するという試み。今回はJavaScript特有の仕組みであるプロトタイプについて。
前回にコンストラクタとインスタンスについて書いた。そこでオブジェクトを得るために、下に示すようにコンストラクタを書いて、そこからインスタンスとしてオブジェクトを得る方法を示した。長方形のオブジェクトを得るためのスクリプトだ。
デモ
長方形オブジェクトのプロパティには色、位置、サイズ(幅、高さ)、移動速度に加え、メソッドとして位置更新関数がある。それらのプロパティとメソッドをそれぞれに持つ、三つの長方形オブジェクトが最後の三行で作られている。
よく考えてみる。色は三つの長方形オブジェクトのあいだで青で統一されている。位置はそれぞれ違う。サイズは常に一定にしてあるので、三つの間で共通だ。移動速度は、それぞれの長方形が枠にあたったときにマイナスをかけて反転するようにしてあるので、三つそれぞれで別の移動速度を持っている。位置更新関数は、文としてはまったく同じものを三つの長方形オブジェクトが持っている。……三つの長方形オブジェクトのあいだで、プロパティとメソッドに重複しているものがある。色、サイズと位置更新関数だ。
内容が重複しているものを三つのオブジェクトそれぞれが持っているなんて不合理じゃないか? それを解消するのがプロトタイプ。コンストラクタRectの定義をちょっと書き直してみる。重複しているものをコンストラクタ定義の外に出して、"Rect.prototype"というプロパティの下に改めて入れてみる。入れる場所をちょっと移しているだけで、内容はまったく変えていない。
デモ
上記のようにコンストラクタを書いて、コンストラクタのprototypeプロパティ以下に変数や関数を追加することで、そのコンストラクタからインスタンス化されたオブジェクトは、自分自身でそのプロパティやメソッドのコピーを持たずにそれらを参照することができる。この仕組み、あるいはコンストラクタの持つprototypeプロパティ自体がいわゆる「プロトタイプ」。
インスタンスがコピーなしにプロパティを参照したり、メソッドを呼んだりできる。そのメリットは使用メモリの削減などの実行効率。プロトタイプの導入はスクリプトの見た目をそれほど変えるものでもない。ということはプロトタイプの導入はオブジェクトが書ければ難しいものではないし、導入の手間もかからない。慣れないうちはプロトタイプなしでオブジェクトを書いてオブジェクトが設計通りに動くことを確認してからプロトタイプを導入するのもあり。オブジェクトが書ける→コンストラクタが書けてインスタンスを作れる→プロトタイプを使える…という手順で修めていけば確実。
****************************************
JavaScriptでオブジェクト指向を学ぶ上で根本的に大事なところを、段階を追って、スクリプトとともに説明を展開してみた。とりあえずここまでをしっかり使えるようになっておくだけでも、書くスクリプトがだいぶ読みやすくなってくる。ここまでをよく理解せずに継承まで進むと、もうオブジェクト指向自体がなんなのかということもぼんやりとしたものになってくる。まずは一つのオブジェクトに特定の機能をまとめることから慣れていくことからオブジェクト指向を始めるといいと思う。
その2 - "コンストラクタ"を使うと類似オブジェクトを作るのが便利
その3 - "プロトタイプ"を使うとオブジェクト作成が合理的になる
番外編 - クラスの概念に縛られた巷のオブジェクト指向の説明
JavaScriptでオブジェクト指向を理解するという試み。今回はJavaScript特有の仕組みであるプロトタイプについて。
前回にコンストラクタとインスタンスについて書いた。そこでオブジェクトを得るために、下に示すようにコンストラクタを書いて、そこからインスタンスとしてオブジェクトを得る方法を示した。長方形のオブジェクトを得るためのスクリプトだ。
デモ
function Rect()
{
this.color = "blue";
this.x = 0;
this.y = 0;
this.w = 50;
this.h = 50;
this.speedX = 3;
this.speedY = 3;
this.update = function()
{
this.x += this.speedX;
if (this.x < 0 || screen.width < this.x + this.w)
{
this.speedX = -this.speedX;
}
this.y += this.speedY;
if (this.y < 0 || screen.height < this.y + this.h)
{
this.speedY = -this.speedY;
}
};
}
var rect1 = new Rect();
var rect2 = new Rect();
var rect3 = new Rect();
長方形オブジェクトのプロパティには色、位置、サイズ(幅、高さ)、移動速度に加え、メソッドとして位置更新関数がある。それらのプロパティとメソッドをそれぞれに持つ、三つの長方形オブジェクトが最後の三行で作られている。
よく考えてみる。色は三つの長方形オブジェクトのあいだで青で統一されている。位置はそれぞれ違う。サイズは常に一定にしてあるので、三つの間で共通だ。移動速度は、それぞれの長方形が枠にあたったときにマイナスをかけて反転するようにしてあるので、三つそれぞれで別の移動速度を持っている。位置更新関数は、文としてはまったく同じものを三つの長方形オブジェクトが持っている。……三つの長方形オブジェクトのあいだで、プロパティとメソッドに重複しているものがある。色、サイズと位置更新関数だ。
内容が重複しているものを三つのオブジェクトそれぞれが持っているなんて不合理じゃないか? それを解消するのがプロトタイプ。コンストラクタRectの定義をちょっと書き直してみる。重複しているものをコンストラクタ定義の外に出して、"Rect.prototype"というプロパティの下に改めて入れてみる。入れる場所をちょっと移しているだけで、内容はまったく変えていない。
function Rect(x, y)
{
this.x = x;
this.y = y;
this.speedX = 3;
this.speedY = 3;
}
Rect.prototype.w = 50;
Rect.prototype.h = 50;
Rect.prototype.color = "blue";
Rect.prototype.update = function()
{
this.x += this.speedX;
if (this.x < 0 || screen.width < this.x + this.w)
{
this.speedX = -this.speedX;
}
this.y += this.speedY;
if (this.y < 0 || screen.height < this.y + this.h)
{
this.speedY = -this.speedY;
}
};
デモ
上記のようにコンストラクタを書いて、コンストラクタのprototypeプロパティ以下に変数や関数を追加することで、そのコンストラクタからインスタンス化されたオブジェクトは、自分自身でそのプロパティやメソッドのコピーを持たずにそれらを参照することができる。この仕組み、あるいはコンストラクタの持つprototypeプロパティ自体がいわゆる「プロトタイプ」。
インスタンスがコピーなしにプロパティを参照したり、メソッドを呼んだりできる。そのメリットは使用メモリの削減などの実行効率。プロトタイプの導入はスクリプトの見た目をそれほど変えるものでもない。ということはプロトタイプの導入はオブジェクトが書ければ難しいものではないし、導入の手間もかからない。慣れないうちはプロトタイプなしでオブジェクトを書いてオブジェクトが設計通りに動くことを確認してからプロトタイプを導入するのもあり。オブジェクトが書ける→コンストラクタが書けてインスタンスを作れる→プロトタイプを使える…という手順で修めていけば確実。
****************************************
JavaScriptでオブジェクト指向を学ぶ上で根本的に大事なところを、段階を追って、スクリプトとともに説明を展開してみた。とりあえずここまでをしっかり使えるようになっておくだけでも、書くスクリプトがだいぶ読みやすくなってくる。ここまでをよく理解せずに継承まで進むと、もうオブジェクト指向自体がなんなのかということもぼんやりとしたものになってくる。まずは一つのオブジェクトに特定の機能をまとめることから慣れていくことからオブジェクト指向を始めるといいと思う。
スポンサーサイト