Kanasan.JS JavaScript 第 5 版読書会 #42008年05月31日 17時57分

Kanasan.JSJavaScript 第 5 版 (サイ本) 読書会 #4 に行ってきました (参加者のブログ記事一覧当日のチャットログ)。

会場、設営

開始 15 分ほど前に会場に着いたのですが人気なし。特に名前のない貸し会議室とのことで、本当にここであってるのか Twitter で他者の動向を探ろうとするも、運悪く Twitter がダウン中。携帯から必死に地図を探していたところにほかの人が到着して一安心となりました。

開始時点で Windows マシン使用者が私を含めて 2 人という脅威のMac率でした。無線 LAN の共有も Mac 機を主体に行われ、そのせいか Windows 機では無線 LAN が利用できず。私は結局 Kanasan さんの EMOBILE 端末を借りてネットに接続しました。

クラス

JavaScript にクラスベースオブジェクト指向言語でいうところのクラスという概念は存在しませんが、サイ本では便宜的にクラスという言葉を使っています。

JavaScript でクラスを模倣する際に使われるのがプロトタイプ (ペアレント) です。クラスベースオブジェクト指向を多平面モデルで説明するのなら、プロトタイプベースオブジェクト指向は平面がひとつしかないという感じでしょうか。オブジェクトとそのプロトタイプは、平面間の垂直関係ではなく、同一平面内のつながり (プロトタイプチェーン) として表現できます。

隠されたプロパティに再び日の目を

あるオブジェクトから delete 演算子で foo プロパティを削除すれば、それにより隠されていたプロパティ (そのオブジェクトのプロトタイプの foo プロパティ) を再び参照できるようになります。

var d = new Date();
d.toString(); // => Sat May 24 2008 12:00:00 GMT+0900 (JST)
d.toString = function () { return this.getDate() + " 日"; };
d.toString(); // => 24 日
delete d.toString;
d.toString(); // => Sat May 24 2008 12:00:00 GMT+0900 (JST)

インスタンスメソッド

function Class() {
  this.f = function () {};
}
Class.prototype.g = function () {};

var instance = new Class();
instance.h = function () {};

f、g、h のいずれもクラスベースオブジェクト指向でいうインスタンスメソッドに相当しますが、一般的には g の形 (プロトタイプのプロパティとして関数オブジェクトを設定) がよく使われます。

比較用のメソッド

Java にならって比較可能なオブジェクトに compareTo メソッドを実装するというお話。that という引数名が読みやすいです。

Class.prototype.compareTo = function (that) {
  return this.x - that.x || this.y - that.y;
};

スーパークラスとサブクラス

コンストラクタ関数の prototype プロパティにスーパークラスのインスタンスを設定することで、クラスベースオブジェクト指向における継承を模倣できます。

function Super() {}
function Sub() {}

var subPrototype = new Super();
Sub.prototype = subPrototype; // (a)
// 通常は下のように 1 行で書く
// Sub.prototype = new Super();

var subInstance = new Sub();
Super.prototype.foo = 42;
subInstance.foo; // (b)

(a) により、Sub オブジェクト (Sub クラスのインスタンス) のプロトタイプは、さらに Super.prototype をプロトタイプとして持つことになります。これは、Super.prototype をコピーしたわけではありません。そもそも JavaScript に C++ のコピーコンストラクタに相当する機能はなく、オブジェクトのコピーが暗黙的に行われることも基本的にはありません。

Super.prototype がコピーされていないことは (b) からも確かめられます。ここで、subInstance は foo プロパティを持っていないため、subInstance のプロトタイプである subPrototype から foo プロパティを探します。subPrototype も foo プロパティを持っていないため、subPrototype のプロトタイプである Super.prototype から foo プロパティを探します。Super.prototype には foo プロパティが存在するので、その値 42 が返ります。

コンストラクタチェーン

サブクラスのコンストラクタ関数内でスーパークラスのコンストラクタを呼び出していくことを、コンストラクタチェーンと呼んでいます。初耳でした。検索してもそこまで一般的な用語ではないような気がします。

継承とオーバーライドされたメソッドの呼び出し

サイ本記載の継承方法には、スーパークラスのコンストラクタを呼び出してしまうという欠点があります。これは一時的なコンストラクタ関数を使うことにより解決できます。ちなみに檜山さんによる「プログラマのための JavaScript」は、JavaScript と他のプログラミング言語との溝を埋める素晴しい連載です。

親クラスのコンストラクタやメソッドを呼び出すために、プロトタイプに superclass プロパティを作るという話が出てきます。このままでは 2 段階以上の継承には使えませんが、継承関係をクロージャに記憶させておくことで解決できます。Prototype.js では Class.create に渡された関数が $super という名前の引数を持っていれば、内部でごにょごにょしてうまいことスーパークラスのメソッドを呼び出せるようにしてくれます。

Object.toString() メソッドによる型判定

function f() {}
Object.prototype.toString.call(f);
// => [object Function]

異なるグローバルオブジェクトから生成されたオブジェクトも同一視したいときなんか便利ですね。

ダックタイピング

ダックタイピングという言葉は詩人 James Whitcomb Riley の言葉から来ているそうです。

JSON Editor

途中ライトニングトークタイムということで、pm11op さん作の JSON Editor の紹介がありました。その名の通りブラウザ上で JSON の編集ができるほか、Adobe AIR 版も用意してありオフラインでも利用可能だそうです。

モジュールと名前空間

モジュール / ライブラリ作成の指針です。このあたりは第 3 版にはなかった内容で、JavaScript が広まるに連れ開発方法も洗練され、一定のパターンができてきたというのを実感させられます。

正規表現パターンマッチング

比較的あっさりした内容となっています。正規表現について詳しく知りたければ「詳説 正規表現」を読んでねということなのでしょうか。

ECMAScript 仕様によればパターン \s は Unicode カテゴリ Zs (space separator) に属する文字 (全角スペースも含まれる) にもマッチするはずですが、ブラウザによって対応は異なるようです (ES3.1 Draft: String generics (PDF) 4 ~ 5 ページに一覧表あり)。

Java をスクリプトする

Java から JavaScript を利用する話 (Java スクリプトエンジン) と JavaScript から Java を利用する話 (LiveConnect)。私の触ったことのない分野です。どうでもいいけど私は昔 Rhino を「りの」と読んでました。

JavaScript でのファイル入出力

JavaScript 単体ではファイル入出力はおろか標準入出力さえ扱えません。しかし、SpiderMonkey のソースコードにはファイル入出力を可能にするその名も File オブジェクトのソースコードが含まれています。とはいうものの、これはデフォルトでは無効化されており、ビルドするためには NSPR が必要です。「SpiderMonkey で File オブジェクト - 陽極日記」には実際にビルドした手順が書かれています。また、OSSP js では、NSPR がなくても File オブジェクトのビルドができるようパッチを当てたソースコードが配布されています。

雑感

Kanasan さんはじめスタッフ及び参加者の皆さんお疲れ様 & ありがとうございました。とうとう第 1 部も終わり、次回からは第 2 部、クライアントサイド JavaScript です。内容も第 3 版から大きく変わっていると思いますので、じっくり読み進めていきたいと思います。