ライブラリとかを作っていると、そのクラス内で全てメソッドを共有してその関数内で処理をまとめて書くのが普通ですよね。
グローバル汚染をしないのが一般的な考え方なもんですが、ここでつまづく方が多い?というか私はすっ転びましたね。
結局は「スコープチェーン」と「参照」の問題なのですが、理解していながらも上手い解決法が見つかりませんでした。
クラス内でクロージャに押し込めた関数内では基本的にクラスのプロパティが参照できません。
例えば、
function class(){
this.num = 1;
this.func = function(){
document.getElementById(‘hogehoge’).onclick = function(){
alert(this.num);
}
this.func()
}
DOMlevel1はそろそろやめないといけないですね(笑)まぁサンプルってことで。
ドキュメントロード時にクラスを生成し、hogehogeのidが付いたものをクリックするとアラートさせるシンプルコード。
しかしこれだとアラート内はundefinedになります。クロージャを知ってたら当たり前ですが。
ドキュメント内でクラスインスタンスを生成していればそのまま変数名でアクセスでき・・・・
といったところで解決しました。
javascriptにおけるオブジェクトは全て「参照渡し」なんですよね。
ってことは、引数にクラスオブジェクトを仮想的に渡して参照させればあら不思議。
引数にはクラスのオブジェクトが「参照」されるので、そのままプロパティにアクセスできるんですね~。知らなかった。
つまり、クロージャに押し込める「前」の階層にクラスオブジェクトを参照させる変数を定義しておく。これがポイント?
function class(){
this.num = 1;
this.func = function(thisclass){
var class = thisclass;
document.getElementById(‘hogehoge’).onclick = function(){
alert(class.num);
}
this.func(this);
}
みたいな感じでやれば、クラス生成時にアラートは1と表示されます。インスタンスを格納する必要が無く、ただnewすればいいだけですね。
スコープの飛び越え、というのは少し違う気がしますが、逆にそのスコープ内にオブジェクトを持ってくる、という逆転の発想?
まぁおのおかげで一つのクラス内でクロージャも使い放題になります。イベント設定とかしてる時には特に便利。
このテの話題が少なかったのでメモ書き程度に。
クロージャは便利であり、厄介でもありますね。
※追記
function.applyでバインドして実行する方法もあるようです。こっちの方がスマートかな。
http://d.hatena.ne.jp/kminoru/20080228/1204250525