主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

JavaScript: オブジェクト指向とクラスとプロトタイプと

                
tags: JavaScript
オブジェクト指向ってなに?→http://elicon.blog57.fc2.com/blog-entry-327.html

 巷に多いクラスベースのオブジェクト指向言語と、JavaScriptというプロトタイプベースのオブジェクト指向言語の差異が理解し切れていなかったのでまとめておく。ときおりJavaScriptがクールな言語でないという意見を見かけることがあるが、それはだいたいクラスを扱う文脈で言われていることで、このクラスを宣言したりインスタンスを作ろうとするあたりにJavaScriptがほかのオブジェクト指向言語と異になっている点があるということがわかる。


 まずオブジェクト指向とは、一つの目的のために使う変数、関数を一つのオブジェクトの下にまとめるようにコーディングをしていくということだ。たとえばJavaScriptで日時に関するデータが欲しいと思ったなら、Dateオブジェクトの中を探せば日時に関するいろんな処理関数がそろっている。ある目的のために使う変数や関数を一つのオブジェクトの下にまとめる。それがオブジェクト指向。
var date = new Date();
alert(date.getDay());
alert(date.getFullYear());
 オブジェクトは一般的に複製を作って使うことが多い。上に書いたスクリプトでもnewを使って、変数dateにオブジェクトDateの複製を作ってから処理をしている。このとき変数dateを、オブジェクトDateのインスタンスと呼ぶ。

 PythonやC#など世間に多いクラスベースのオブジェクト指向言語では、クラスというものを宣言して、そのクラスを参考にして複製物を作る。クラスは設計図のような役割をする。
Python
class Foo:
def foo1(self):
print "fooooooooooooo"

Foo().foo1()


 JavaScriptではインスタンスの元となるオブジェクトを関数オブジェクトを使って作るのが一般的。それを複製してインスタンスを利用する。おそらくJavaScriptのオブジェクト指向が嫌われるのはこういう方法でインスタンスの元を作るところ。関数として宣言されているものが、ただ単純な流れの処理を任せたいだけの関数なのか、インスタンスの元になる関数オブジェクトを宣言しているのかわかりづらくなる。ちなみにこのインスタンスの元になる関数オブジェクトをコンストラクタと呼ぶ。
function Foo(){
this.foo1 = function(){alert("foooooooooo");};
}

(new Foo()).foo1();


 以上がおおまかなJavaScriptでのインスタンスの元となるオブジェクトの作り方。たとえば長方形に関するオブジェクトを作って使いたいときは以下のように。
function Rect(w, h){
this.w = w;
this.h = h;
this.getArea = function(){return this.w * this.h;};
}

var rect1 = new Rect(3, 5);
alert(rect1.getArea());
var rect2 = new Rect(5, 5);
alert(rect2.getArea());
var rect3 = new Rect(10, 10);
alert(rect3.getArea());


 ……プロトタイプが出てきていない。JavaScriptはプロトタイプベースのオブジェクト指向言語といわれる。でもプロトタイプを使わずに、任意のオブジェクトに変数や関数をまとめることができてしまった。このようにプロトタイプは必ずしも必須ではない……と思う。
 ではなぜプロトタイプという概念があるのか。それは処理の実行を効率的にするためだろう。真上に書いたスクリプトでは、オブジェクトRectを元にして複製すると、プロパティw,hとメソッドgetAreaの3つのメンバをもつオブジェクトができる。でもメソッドgetAreaは式が共通だから、それとまったく同じものが複製を作るたびにできるのって合理的じゃない。メソッドgetAreaは一箇所で定義しておいて、インスタンスのあいだでそれを使いまわしたい。そんなときに使うのがプロトタイプ。
function Rect(w, h){
this.w = w;
this.h = h;
}

Rect.prototype.getArea = function(){return this.w * this.h;};

var rect1 = new Rect(3, 5);
alert(rect1.getArea());
var rect2 = new Rect(5, 5);
alert(rect2.getArea());
var rect3 = new Rect(10, 10);
alert(rect3.getArea());

以上のように書けば、メソッドgetAreaがインスタンス作成のたびに作られることはなく、インスタンスのあいだで使いまわすことができる。これがプロトタイプ。インスタンスの元になるオブジェクト(試作品)から、使いまわせる必要な要素を拝借してしまおうという仕組み。利点は処理が合理的になること。ただしいつでも必須のテクニックというわけでもなく、今回のような非常に小さいスクリプトだとえられる恩恵はかなり小さい。


参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Details_of_the_Object_Model




おまけ****************************
 本文で書いたことをまとめると、「コンストラクタを使えば、ある目的のために使う関数や変数を一つのまとまりにして、コピーしてその複製物を簡単に作れるようになる」ということ。一つのまとまりに変数をぶっこんだ恩恵として、グローバル変数を使わなくすることができる。
 グローバル変数を減らせる手段としてクロージャというものもある。複製を作らないからコンストラクタは使う必要がない、だけどグローバルスコープから変数を退避させたいとなれば、クロージャを使うのも一考。
クロージャデモ
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。