Jaml などのHTML ジェネレータを調べてる際に気付いたことだが、javascript では、引数に渡す無名関数内のみに関数を公開する方法がある。
[Jaml のサンプルコード]
上記サンプルの無名関数内で呼び出している div や h1 などの関数は、外部に公開されていない(グローバル関数ではない)。
どうやって実現しているのかさっぱり分からなかったので、Jaml のソースを拝見。
div や h1 は Jaml.Template の prototype 関数で、with と eval で実現できる模様。
[実現コード]
prototype 関数でなければ with で囲む必要はない。
上記例で、Test.console 内に定義した関数なら、外部に公開されず、引数の callback 内でのみ使える関数となる。
Jaml.register に渡す無名関数の第一引数に Jaml.Template インスタンスが渡されるので、そこから div や h1 などのメソッドを使う。
[Jaml のサンプルコード]
Jaml.register('sample', function(){
div(
h1('サンプル'),
p('Jaml です。'),
br()
);
});
上記サンプルの無名関数内で呼び出している div や h1 などの関数は、外部に公開されていない(グローバル関数ではない)。
どうやって実現しているのかさっぱり分からなかったので、Jaml のソースを拝見。
div や h1 は Jaml.Template の prototype 関数で、with と eval で実現できる模様。
[実現コード]
//[定義]
var Test = {
console : function(callback){
var logger = new Logger();
//・callback を文字列展開して eval 実行することで、
// callback の変数スコープをこの関数内に変更
//・with を使って prototype 関数に直接アクセス
with( logger ) eval('(' + callback.toString() + ').call(logger)');
}
};
var Logger = function(){ this.count = 0; };
Logger.prototype = {
log: function(message){
console.log(message);
this.count++;
},
};
//[実行]
Test.console(function(){
log('one');
log('two');
log(count);
});
//[結果]
// one
// two
// 2
prototype 関数でなければ with で囲む必要はない。
上記例で、Test.console 内に定義した関数なら、外部に公開されず、引数の callback 内でのみ使える関数となる。
おまけ
本題とはあんまり関係ないけど、Jaml から eval と with を除いたもの。Jaml.register に渡す無名関数の第一引数に Jaml.Template インスタンスが渡されるので、そこから div や h1 などのメソッドを使う。
0 件のコメント:
コメントを投稿