Hatena::Groupsubtech

冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

 | 

Oct 03, 2012 (Wed)

micro-template.js について 01:28 はてなブックマーク - micro-template.js について - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

LTソンでちょっと喋れたのはいいけど、ちょっと説明不足の部分があって、あーと思ったので書き残しておきたいと思います。

これは John Resig 氏が 2008 年 (!) に書いたテンプレートと互換性を持つテンプレートエンジンで、以下のような特徴があります。

  • 既存の John Resig 氏の tmpl() を置き換えて使用することが可能
  • 実行時エラーが発生した場合に、エラーが発生した行数を表示可能
  • source map に対応していれば、syntax エラーも行数を表示可能
  • 割と早い
  • デフォルトでHTMLエスケープ

そもそもの動機としては「エラーメッセージちゃんと出したい」というもので、なんとなく「無理矢理こうしたらうまくいきそう」というアイデアを実装してみた、というものを元に少々の改良を加えたものになっています。

with() 最適化

John Resig 氏の tmpl() に互換にするためには、with() で変数を展開するというのが不可欠になってきます。パフォーマンス的には with() を使わずに

  1. あらかじめテンプレートで使う変数名を列挙
  2. 特定のオブジェクトに全ての変数をプロパティとしてセット

などしたほうがいいのですが、互換を目指す以上 (あるいは使い勝手という意味で) with() で変数を展開するというのははずせませんでした。

しかし with() のパフォーマンス劣化は非常に有名なほど著しいものなので、できれば十分高速にしたいと思い、既知の変数に関しては this を経由してアクセスするというクソハックをしています。

どういうことかというと、出力する文字列のバッファには this.ret、行番号に関しては this.line というプロパティをローカル変数の変わりに使うようにします。this は変数ではなく、特定の値を参照するキーワードであるため、with によるスコープチェインへの割り込みの影響をうけません。

これにより、既知の変数については with() の影響をうけなくなるため高速化されます。

特殊タグの置き換え

コンパイルタイムの短縮のため、正規表現で一括置換という構造を変えたくなかったため、<% %> というタグを \x11 (XON) \x13 (XOFF) というコントロールキャラクタ1文字に置換してから処理をしています。1文字にすることで正規表現で否定表現が書きやすくなって便利です。\x11 と \x13 が使えなくなりますが、まず使わないので気にしないことにしています。

速度厨用あるいはベンチマーク用

with() を多少高速化したといっても、既知ではない変数参照はあいかわらず遅いので、一応 with() を使わないようにもできるようになっています。

template.variable = 's';

などと指定すると、with() が無効になり、s に全部の変数が入ってくるようになり s.foobar という形でアクセスするようになります。この場合 with() による速度悪化がなくなるので、だいたいこれ以上早くならないだろ、ぐらいまで早くなると思います。

 | 

スポンサード リンク

書いてる人

cho45 (佐藤広央) (www.lowreal.net)

Perl, JavaScript, Ruby, HTML, CSS, Web etc


スポンサード リンク