JavaScript Diary

テクニック [ 2001/07/06 ]
コンストラクタ関数内で HTML オブジェクトを書き出すことは多々ありますが、そのとき DHTML などで、イベントハンドラで自分自身を参照したい場合がよくあります。これから説明するテクニックは非常に重要なので覚えておいた方が良いです。てか、これをマスターすれば世界が変わります。では、プログラムを見てください。
function Hoge( id ){
    
    this.id = id ;
    
    document.writeln(
        "<a href=\"#\"",
        "onClick=\"return false;\">",
        "sample text",
        "<\/a>"
    );
    
}

Hoge.prototype.call = function(){ alert( this.id ); };
このプログラムの onClick の中で自分自身の call メソッドを呼び出したいときどうすれば良いでしょうか? 一番最初に思いつき、かつ一番やってはいけないのが以下の方法です。
function Hoge( id ){
    
    this.id = id ;
    
    document.writeln(
        "<a href=\"#\"",
        "onClick=\"obj.call();return false;\">",
        "sample text",
        "<\/a>"
    );
    
}

Hoge.prototype.call = function(){ alert( this.id ); };

var obj = new Hoge( "MyId" );
確かにリンク部分をクリックすれば、MyId の文字列がアラートに表示されますが、これは obj という名前を持つインスタンスのみに有効で、次に obj1 という別のインスタンスを生成しても参照するのは obj で、こういう風にしてしまうとクラス化の利点がなくなってしまいます。
じゃー汎用性を持たせて obj 部分に this を使おうと思うかも知れませんが、意外に勘違いしてしまうのが次の方法です( onClick 部分のみ )。
onClick=\"this.call();return false;\"
これはうまく行きそうなのですが、クリックしても「call なんていうメソッドは存在しません」とかいうエラーが発生して終わりです。これは this が(インスタンス変数ではなく)リンクオブジェクトを参照するためです(考えてみれば当たり前です)。
前置きが長くなって申し訳ないですが、苦労日記ということで勘弁して下さい(というかコレ日記でしたね。笑)。
要は自分自身をグロバールな値に保持させ、onClick 部分でそのグローバルな値から自分自身を参照すれば良いのです。結論は以下ですのでじっくり見てみて下さい。
function Hoge( id ){
    
    this.id = id ;
    
    var index = document.links.length ; // 現在のリンク数を保持しておく
    
    document.writeln(
        "<a href=\"#\"",
        "onClick=\"document.links["+index+"].$CP.call();return false;\">",
        "sample text",
        "<\/a>"
    );
    
    // ここが重要!
    // グローバルオブジェクト、自身で生成したリンクオブジェクトの
    // プロパティ $CP に自分自身を参照させる。
    document.links[ index ].$CP = this ;
    
}

Hoge.prototype.call = function(){ alert( this.id ); };

var obj0 = new Hoge( "MyId0" );
var obj1 = new Hoge( "MyId1" );
var obj2 = new Hoge( "MyId2" );
こうすることでバッティングもほぼ皆無になり、汎用性、再利用性が飛躍的に向上します。この場合、onClick 部分に this を使ってもっとスマートに下のように書くこともできます。
function Hoge( id ){
    
    this.id = id ;
    
    var index = document.links.length ;
    
    document.writeln(
        "<a href=\"#\"",
        "onClick=\"this.$CP.call();return false;\">",
        "sample text",
        "<\/a>"
    );
    
    document.links[ index ].$CP = this ;
    
}
onClick 部分の this はリンクオブジェクトを参照します。このテクニックは非常に強力なので是非マスターして下さい。つづく・・・