prototype.js ってなに?の巻

追記 2005-08-23

Using prototype.js v1.5.0
リファレンスがあったみたい。これを読んだ方がはるかに有益です。あー書くんじゃなかった。

はてなの人気者 id:naoya が「prototype.jsデザインパターン」というのをやってるんだけど、prototype.js の説明をしてくれなくて困る。前から「Railsprototype.js は便利だ」というのを目にすることがあったので、ちょうどいい機会だってことで調べた。
http://prototype.conio.net/
ドキュメントが全然ない。ないこたないと思うのでご存知の方は教えてください。しょうがないのでコードを読むことに。
http://dev.conio.net/repos/prototype/src/
ここのを順次読みます。

base.js

http://dev.conio.net/repos/prototype/src/base.js
クラス定義に関わる基本的なものなどが書いてある。
コンストラクタには

var Class = {
  create: function() {
    return function() { 
      this.initialize.apply(this, arguments);
    }
  }
}

これを使えということらしい。下みたいにするとクラスがひとつ出来上がり、って風に使うんでしょう。

var Person = Class.create();

みんなが見慣れてるであろう作法に書き直すとこう。

function Person() {
  this.initialize(arguments);
}

arguments っていうのは引数を表すオブジェクトで、引数が入ってる配列みたいに考えるとまあいい。
http://www.interq.or.jp/student/exeal/dss/ref/jscript/object/arguments.html
一見何も引数をとらないみたいだけど、argumentsを使って任意の引数をとれるようにしているわけです。あと初期化メソッド initialize はどこから出てきたかというと、これは後から自分で定義する。

Person.prototype = {
  initialize: function(name) {
    this.name = name;
  }
};

つぎは継承について。これを使うみたい。

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}
Object.prototype.extend = function(object) {
  return Object.extend.apply(this, [this, object]);
}

使用法はこんな感じか。

var Hatener = Class.create();
Hatener.prototype = (new Person()).extend({
  initialize: function(name, id) {
    Person.prototype.initialize.call(this, name);
    this.id = id;
  }
});

基本的な考え方は次のページを参考に。書き方は違うけどやってることはだいたい同じです。
http://www.interq.or.jp/student/exeal/dss/ejs/3/2.html
簡単に説明すると、親クラスのインスタンスにプロパティをくっつけたりオーバーライドしたりして、それを子クラスのプロトタイプにする。そうするとプロトタイプチェーンを巡って親クラスで定義されたプロパティにもアクセスできる。注意点としては、ダミーの親インスタンスを作る時に呼ばれる initialize() が悪いことをしないように気をつけなきゃいけない。
クラスがどうとかはここまで。残りを見ます。Function.prototype.bind と Function.prototype.bindAsEventListener はあった方がずっといいというかこれはなきゃいけないなあ。いつも

var self = this;

って書きまくってたよ。イベントはこうやると互換が楽なのかあ。勉強になるなあ。
Try とか PeriodicalExecuter とかは特に説明しなくていいや。

dom.js

http://dev.conio.net/repos/prototype/src/dom.js
DOM操作のいろいろ。
document.getElementsByClassName は読んで字の通り。その後は Element のクラスメソッドがいくつか。toggle とか hide とか、JavaScript を触ったことがある人なら必ず書いたことがある感じの。動的にエレメントの className を変える場合複数のクラス名を指定することが多くなるので、ここにある className の操作メソッドも重要。残りの部分は IE独自 の insertAdjacentHTML 的なものを実装してる。こんなの知らなかったなあ。

event.js

http://dev.conio.net/repos/prototype/src/event.js
ブラウザの互換性をとる時にかなりめんどくさいイベント処理。まずリスナーの引数に与えられたイベントオブジェクトか window.event かってとこで IE のバカって思うんだけど、そこは base.js の

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}

で解決。event.js では pageX や preventDefault あたりの互換と、もっといろいろやってくれると助かるんだけどそこら辺はサイズとの兼ね合いがあるだろうからまあいいとして、あと Event.observe と Event.stopObserving でイベントリスナーの登録解除ができるようにする。まっとう。

form.js

http://dev.conio.net/repos/prototype/src/form.js
あーこれ便利。スクリプトでフォームから値を得ようとするとチマチマしててすごくイライラするんだけど、Form.serialize(form) 一発でクエリが得られる。あとイベントリスナーを簡単にとか。TimedObserver なんかは今どきの Ajax な感じ。

position.js

http://dev.conio.net/repos/prototype/src/position.js
これもめんどくさいエレメントの位置関連をちょこっと。どんどん説明が適当になってきた。

ajax.js

http://dev.conio.net/repos/prototype/src/ajax.js
XMLHttpRequest の wrapper と、それの responseText をエレメントの innerHTML に直接流し込む版が書いてある。

まとめ

便利で適度にコンパクトで素敵だと思います。終わり。

ちゃんとしたプログラミングの勉強をしたことがないのでこれからする。たぶんまず「データ構造とアルゴリズム」みたいのをやればいいんだろうと思ってこれを借りてきたのでちゃんと読む。

アルゴリズムC・新版―基礎・データ構造・整列・探索

アルゴリズムC・新版―基礎・データ構造・整列・探索