Hatena::ブログ(Diary)

Islands in the byte stream

2011-02-26

JavaScriptにおけるオブジェクトの定義

JavaScriptで一番簡単にオブジェクト指向プログラミングを行う方法 (id:perlcodesample)

私は特にJavaScriptに詳しいわけではなく、オライリーの『JavaScript』、通称サイ本を読んだ程度なのですが、私の知るかぎりJavaScriptでオブジェクト*1を定義する方法には二つの軸があります。一つ目はオブジェクトの生成方法で、二つ目はメソッドの与え方です。すなわち:

  • new演算子で生成する / オブジェクトリテラルで生成する
  • prototypeによってメソッドを生やす*2 / プロパティを直接代入してメソッドを生やす

これについて具体的に説明してほしいとのことでしたので、以下にこの二つの軸の組み合わせ、計4つの方法を示します。

(実行可能なコードはjsdo.itにて: http://jsdo.it/gfx/9LR3)

var pointToString = function(x, y) {
  return '(' + this.x + ', ' + this.y + ')';
};

// new + prototype
var Point0 = function(x, y) {
  this.x = x;
  this.y = y;
};
// Point0オブジェクトの__proto__プロパティは
// Point0.prototypeが与えられる
Point0.prototype.toString = pointToString;

var p0 = new Point0(10, 20);

// new  + properties
var Point1 = function(x, y) {
  this.x = x;
  this.y = y;
  this.toString = pointToString;
};

var p1 = new Point1(10, 30);

// factory + prototype
var Point2_prototype = { toString: pointToString };
var createPoint2 = function(x, y) {
  var object = { x: x, y: y };
  // __proto__を手動で与える
  object.__proto__ = Point2_prototype;
  return object;
};

var p2 = createPoint2(10, 40);

// factory + properties
var createPoint3 = function(x, y) {
  var object = { x: x, y: y };
  object.toString = pointToString;
  return object;
};

var p3 = createPoint3(10, 50);

さて、この4分類に従うと、id:perlcodesample さんの記事は「オブジェクトリテラル+プロパティに直接代入(factory + properties)」の組み合わせということになります。

これに対して私の意見は、メソッドの与え方としてprototypeを使うべきではないかいうものです*3。コンストラクタをシンプルに保ちメソッドの定義を分離すること、オブジェクトを生成しなくてもメソッドにアクセスする方法を提供できる*4ことなどがその理由です。

*1:この記事では"オブジェクト"を"プロパティとメソッドをもったデータ"という意味で使ってます。

*2:実際にはメソッドに限らず、任意のプロパティを与えることができます。

*3:オブジェクトの生成方については特に意見はありません。

*4:上記の例ではPoint0.prototype.toString

hasegawayosukehasegawayosuke 2011/02/28 12:26 wow! cool!

tokuhiromtokuhirom 2011/02/28 12:30 wow! cool!

mattnmattn 2011/02/28 12:32 wow! cool!

gfxgfx 2011/02/28 15:17 [これはひどい]

yappoyappo 2011/02/28 16:01 wow! cool!

yappoyappo 2011/02/28 16:01 wow! cool!

perlcodesampleperlcodesample 2011/02/28 23:13 __proto__はIE8より前のバージョンでは動かないそうなので、現実的な選択としては利用できないとコメントをもらいました。またプロトタイププロパティ(オブジェクト.prototype)とプロトタイプオブジェクト(__proto__)は別の概念のようなので、prototypeによってメソッドをはやすといういいかたは誤解を招く気がします。

gfxgfx 2011/03/01 10:10 >perlcodesampleさん

見ました。prototypeはECMAScript標準ですが、__proto__はそうではないようですね。難しい。
おそらく最適解としては、メカニズムは基本だけ押さえておき、実際に使うには(Perlでそうするように)クラスビルダー的なライブラリを使って定義したほうがいいのかもしれません。

最近発売された『JavaScriptパターン』がベストプラクティス集といった感じでよさそうに思えましたので私もこれで勉強しなおします。
http://blog.livedoor.jp/dankogai/archives/51629443.html

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/gfx/20110226/1298705892