2007年05月18日 14:15 [Edit]
javascript - 関数をtraceする
amachangのコメントを受けて追記 JavaScript: 関数の追跡 - 文系大学的IT系の悲哀からのTBを受けて追記
書き換えめんどいー。
IT戦記 - JavaScript の関数を「引数そのまま返す化」alertだけ
alert(hoge); hoge.method();改行めんどいー。
alert + そのまま返す化
alert.s(hoge).method(); // 1 ステートのまま
Functionオブジェクトを拡張
というわけで、関数をtraceするmethodをFunction Objectに追加してみる。
まずは実例。
実装はこう。
Function.prototype.trace = function(name, tracer){
var self = this;
if (!name) name = this.name || '__ANON__';
if (!tracer) tracer = function(n, a, r){
alert( n + '(' + a.join(', ') + ') = ' + r);
};
return function(){
var retval;
try{
retval = self.apply(this, arguments);
}catch(e){
retval = e;
}
var a = [];
for (var i = 0, l = arguments.length; i < l; i++){
a[i] = arguments[i]
}
tracer(name, a, retval);
return retval;
}
}
これなら何でもtraceできる。しかし関数名をtraceの引数に入れないといけないというのが面倒(その代わり、無名関数でもtraceできる)。
trace()を関数として実装
以下はFunction Objectを拡張するのではなく、通常の関数としてtrace()を実装した例。
function trace(name, obj, tracer){
if(!obj) obj = window;
if(!(name in obj)){
throw new Error("No '" + name + "' method in object " + obj);
}
if (!tracer) tracer = function(n, a, r){
alert( n + '(' + a.join(', ') + ') = ' + r);
};
var orig = obj[name];
obj[name] = function(){
var retval;
try{
retval = orig.apply(this, arguments);
}catch(e){
retval = e;
}
var a = [];
for (var i = 0, l = arguments.length; i < l; i++){
a[i] = arguments[i]
}
tracer(name, a, retval);
return retval;
};
}
使い方は、こう。
function mul(x,y){ return x * y }
trace('mul');
mul(2, 4);
ただし、見ての通り関数名を文字列として渡してあるので、無名関数には使えないし、レキシカル関数にも使いにくい。例えば、以下はエラー。
(funcition(){
function mul(x,y){ return x * y }
trace('mul');
mul(2, 4);
})();
こうすれば動く。
(funcition(){
var o = {};
o.mul = function(x,y){ return x * y };
trace('mul', o);
o.mul(2, 4);
})();
まとめ
DRYさは損なわれるが、Function.prototype.trace()の方がJavaScriptっぽいように思う。
Enjoy!
Dan the JavaScripter
追記:
Function#nameはstandardではないとのこと。
Core JavaScript 1.5 Reference:Global Objects:Function - MDCname: The name of the function (not part of the standard).
それでも、上記のように書き換えてもsafeなのでそうしましました。
追^2記:
JavaScript: 関数の追跡 - 文系大学的IT系の悲哀ただ、Function.prototype.traceの中の10行目で、retval = self.apply(null, arguments);と、やってしまっているので、オブジェクトのメソッドをtraceしようとするとうまくいきません。
というわけで、nullをthisに変更しました。今度はうまく行くはずです。
Posted by dankogai at 14:15│Comments(3)│TrackBack(2)
この記事へのトラックバックURL
この記事へのソーシャルブックマーク
この記事へのトラックバック
IT戦記: JavaScript の関数を「引数そのまま返す化」404 Blog Not Found: 関数をtraceする
この二つのブログには本当にお世話になっているんだが、相変わらずすごい。っていうか、よくこんなおもしろいことを思いつくなあ。
関数のトレース【文系大学的IT系の悲哀】at 2007年05月19日 00:39
http://d.hatena.ne.jp/amachang/20070517/1179427742 http://blog.livedoor.jp/dankogai/archives/50833481.html とかスマートだなあと思いつつ。 昔なんかやったよなあとか思ったらあった。 Kumuでコメントアウトにしてる部分だね。 元々AOPみたいなの作ってたんだな。 抜
[Kumu]関数のtrace【回転と脱線】at 2007年05月29日 14:12
この記事へのコメント
おお!先にやられた!
try { } catch(e) { } でエラーも trace 出来るとかなり実用的。
あと、 name は省略可能で this.name (関数の name プロパティ)から取ったらよりカッコいいかも。
と思いました!
try { } catch(e) { } でエラーも trace 出来るとかなり実用的。
あと、 name は省略可能で this.name (関数の name プロパティ)から取ったらよりカッコいいかも。
と思いました!
Posted by amachang at 2007年05月18日 15:16
弾先生。
腐りきった、この世界に、一発どでかいゲームを打ち込んでみませんか!!
↓私のブログとメールアドレスです。気になったら、いつでも連絡下さい!!
http://d.hatena.ne.jp/mgcc/
moegi3212000@yahoo.co.jp
( ´∀`)σ)´Д`)プニュ
腐りきった、この世界に、一発どでかいゲームを打ち込んでみませんか!!
↓私のブログとメールアドレスです。気になったら、いつでも連絡下さい!!
http://d.hatena.ne.jp/mgcc/
moegi3212000@yahoo.co.jp
( ´∀`)σ)´Д`)プニュ
Posted by 大勲位モーリス・G・茶茶 at 2007年05月18日 18:20
ナルホド(^ω^)
Posted by 劇ちん at 2007年05月19日 15:45

