Show page source of インスタンスベースのオブジェクト指向の支援ライブラリ「base.js」 #100185

== base.jsとは
「base.js」とは、インスタンスベースのオブジェクト指向プログラミングを支援するためのJavaScriptライブラリです。SIEを軽量化するために作られた、自身も軽量なライブラリ( gzip圧縮で621バイト)です。オープンソースで、MITライセンスを採用しています。
== 特徴
 1. オープンソース
 2. インスタンスベースのオブジェクト指向プログラミングの支援
 3. JavaScriptで記述
 4. 軽量なライブラリ
== ダウンロード
[http://sourceforge.jp/projects/sie/releases/ SIEのパッケージ]をダウンロードしてください。パッケージを解凍した後、その中にある tool/funcproto/ ディレクトリに、base.jsというファイルがあります。
== Git
ソースコードはGitで取得できます。マスターブランチのレポジトリ、http://sourceforge.jp/projects/sie/scm/git/sie/tree/master/tool/funcproto/
 をご覧下さい
== サンプルコード

{{{
base("$hoge").mix( {

  init: function () {}

} ).up("$hogehoge");

base("$hoge").init();
}}}
別の書き方もできます。

{{{
base("$hoge").up("$hogehoge");

base("$hoge").mix( {

  init: function () {}

} );
}}}
できるだけ、簡単に書けるように、また、さまざまな書き方ができるようにすることで、オブジェクト指向プログラミングを軽量化できるのです。
== 初心者のための導入手順
ここでは、ブラウザ上で使いたいときに、JavaScript初心者のために、base.jsを導入するためのやり方を述べていきます。まず、SIEをダウンロードをして、tar.gz形式のパッケージを解凍します。解凍できましたら、tool/funcproto/ディレクトリにある、「base.js」という名前のファイルを、自分の好きなディレクトリにコピーしてください。コピー先のディレクトリを仮に「doc」としておきましょう。これで、準備はすみました。
=== ここまでの確認
 1. SIEをダウンロードして、解凍
 2. 「base.js」というファイルがあるので探す
 3. 2のファイルを好きなディレクトリにコピー
続けて、HTMLファイルを用意して、docディレクトリにいれます。できましたら、そのHTML文書に、次の一文を追加してください。(処理を早くするため、できれば、body要素の終了タグの前がいいでしょう)
{{{
 <script src='base.js' type='text/javascript'></script>
}}}
これが、base.jsを読み込むためのscriptタグとなります。
さらに、今度はサンプル用のJavaScriptファイルを用意します。ここでは仮に「sample.js」としておきます。これもHTMLファイルと同じように、docディレクトリにいれておきましょう。
先ほどのHTMLファイルを文書エディターで開いて、<script>タグを書いておいた場所に、次の一文を追加します。
{{{
 <script src='sample.js' type='text/javascript'></script>
}}}
さて、sample.jsに次のようなコードを書いてみましょう。
{{{
base("$hoge").mix( {

  init: function () {
    alert("Hello! World");
  }

} );

base("$hoge").init();
}}}
後はブラウザを起動して、作ったHTMLファイルを読み込めば、Hello! Worldという文書がポップアップで表示されて、これで成功です。
=== ここまでの確認
 1. HTML文書を用意
 2. 1で用意した文書に、base.jsを読み込むための、scriptタグを書き込み追加
 3. 別に、サンプル用のJavaScriptファイルを用意して、同様にscriptタグを追加
 4. 1のHTML文書をブラウザで読み込めばOK
== API
base.jsでは、いろいろな関数やメソッドを用意していますので、それを解説していきます。
=== base 関数
オブジェクトを生成、参照するために、呼び出す関数です。引数には、文字列を使って、オブジェクトの名前を付けます。
返り値は、生成したオブジェクトとなります。
{{{
base("$hoge");
}}}
作ったオブジェクトを参照したい時は、同じ名前で呼び出すことができます。
{{{
( base("$hoge") === base("$hoge") ); // true
}}}
このbase関数によって作られたオブジェクトには、あらかじめ、いくつかメソッドが用意されています。これらのメソッドを使うことで、オブジェクト指向プログラミングを実現します。
=== mix メソッド
オブジェクトを合成したい時に使います。強力なメソッドです。引数には、合成しておきたいオブジェクトを入れます。
例えば、$hogeオブジェクトにhogehogeメソッドを指定してみましょう。
{{{
base("$hoge").mix( { 
  hogehoge: function(){}
} );
}}}
指定したhogehogeメソッドの呼び出しは以下のとおりです。
{{{
base("$hoge").hogehoge();
}}}
このサンプルコードでは、$hogeオブジェクトに、hogehogeメソッドを定義しています。
もちろん、オブジェクトリテラル以外でも、別のオブジェクトでも構いません。
{{{
base("$$hoge").mix( base("$hoge") );
}}}
また、引数には関数を使うことができます。
{{{
base("$hoge").mix( function() {} );
}}}
このmixメソッドの返り値は、レシーバのオブジェクトですので、メソッドチェーンを使うことができます。
{{{
base("$hoge").mix({})
               .mix({});
}}}
=== up メソッド
オブジェクトの継承をするために、新しいオブジェクトを作るメソッドです。引数には、文字列を使って、新しく作るオブジェクトの名前をいれておきます。
{{{
base("$parent").up("$child");
}}}
返り値は新しく作ったオブジェクトです。この新規オブジェクトは、レシーバのオブジェクトを継承できます。
継承すれば、親のメソッドやプロパティを使えるようになります。
{{{
base("$parent").mix( {
  hoge: function() {
    return 12;
  }
} );

base("$parent").up("$child").hoge(); //12
}}}
$childオブジェクトは$parentオブジェクトのメソッドが使えるので、$parentオブジェクトを継承しているわけです。

また、次のように、一度作ったオブジェクトは、親オブジェクトのプロパティで参照します。
{{{
base("$parent").$child;

base("$parent").$child.hoge(); //12
}}}
このような機能を、名前空間と呼びます。
=== on メソッド
メソッドの合成ができるメソッドです。おもに、非同期処理や初期化などで使います。
第一引数には、メソッド名が、第二引数には、関数が入ります。
{{{
base("$hoge").mix( { 
                  hogehoge: function(){}
                } )
               .on( "hogehoge", function() {});

base("$hoge").hogehoge(); //hogehogeメソッドを呼び出す
}}}
関数は登録された順に実行されますので、ご注意下さい。なお、hogehogeメソッドが始めからない場合、最初に指定したonメソッドの関数が、メソッドとして登録されます。
次のコードでは、xプロパティを1ずつ足していくhogehogeメソッドを作っています。
{{{
base("$hoge").on( "hogehoge", function() {
                      this.x = 0;
                      this.x++;
                })
               .on( "hogehoge" , function() {
                      this.x++;
                });

base("$hoge").hogehoge();
base("$hoge").x;           // 2;
}}}
第二引数で指定した関数のthisに注目してください。
このthisは、束縛されていませんので、レシーバである$hogeオブジェクト ( つまり、 base("$hoge") の返り値 )を表しているのです。
また、メソッドの引数を、関数の引数に引き継ぐことができますので、初期化も可能です。
{{{
base("$hoge").on( "initialize", function(obj) {
                      this.px = obj.x;
                })
               .on( "initialize" , function(obj) {
                      this.py = obj.y;
                });

base("$hoge").initialize( {
                  x: 2,
                  y: 3
                } );
base("$hoge").px;           // 2;
base("$hoge").py;           // 3;
}}}
このメソッドの利点は、upメソッドでも合成を引き継ぐことです。
試しに、さきほどの初期化コードを、upメソッドを使って、$childオブジェクトにも使えるようにしましょう。
{{{
base("$hoge").on( "initialize", function(obj) {
                      this.px = obj.x;
                })

               .up("$child")

               .on( "initialize" , function(obj) {
                      this.py = obj.y;
                });

/*$childオブジェクトでinitializeメソッドを実行*/

base("$hoge").$child.initialize( {
                  x: 2,
                  y: 3
                } );
base("$hoge").$child.px;           // 2;
base("$hoge").$child.py;           // 3;
}}}
これを使えば、初期化のみならず、非同期処理にも応用できるでしょう。