unoh.github.com

prototype.jsへの依存を無くす方法

Mon Jan 15 01:22:20 -0800 2007

komagataです。

Javascriptで何か書こうと思ったときにどのライブラリをベースにして作るかで非常に悩みます。一端特定のライブラリに依存してしまうと途中で変更するのが難しそうですし、コアオブジェクトを汚染しているものは混ぜると動かなくなる組み合わせもあります。

別に「Mochikitにしよう!」とか宣言して決めてしまえばいいじゃないかという意見もありますが、妙にそんなところが気にかかってなかなかプログラムを書き始められないことが多いです。

そこで、「どうしても使いたい関数はインライン化すればいいんじゃないか?」と思ったので試してみました。

どういうことかというと、例えばprototype.jsのObject.extendを使って以下のように書きたいところを・・・

var dst = {'foo':1, 'bar':2};
var src = {'foo':100};
var result = Object.extend(dst, src);


こんな感じで同じ動作をする無名関数に置き換えるということです。

var dst = {'foo':1, 'bar':2};
var src = {'foo':100};
var result = (function(d,s){for(var p in s)d[p]=s[p];return d})(dst, src);


コード量が増えるのでやりすぎると遅くなってしまいます。なるべく依存関数を使わずに書いて、どうしても使いたいところだけこうするのが良さそうです。

そういう関数を他にもいくつか作ってみました。

prototype.jsのObject.extend

(function(d,s){for(var p in s)d[p]=s[p];return d})


prototype.jsのElement.getDimensions(Elementの幅や高さを取る関数)

(function(e){if(typeof e=='string')e=document.getElementById(e);if(e.style.display!='none')return {width:e.offsetWidth,height:e.offsetHeight};var s=e.style;var o=s.visibility;var r=s.position;s.visibility='hidden';s.position='absolute';s.display='';var w=e.clientWidth;var h=e.clientHeight;s.display='none';s.position=r;s.visibility=o;return {width:w,height:h}})


scriptaculousのElement.setOpacty(透明度を変更する関数)

(function(e,v){if(typeof e=='string')e=document.getElementById(e);if(v==1){e.style.opacity=(/Gecko/.test(navigator.userAgent)&&!/Konqueror|Safari|KHTML/.test(navigator.userAgent))?0.999999:1.0;if(/MSIE/.test(navigator.userAgent) && !window.opera)e.style.filter=e.style.filter.replace(/alpha\([^\)]*\)/gi,'');}else{if(v<0.00001)v=0;e.style.opacity=v;if(/MSIE/.test(navigator.userAgent) && !window.opera)e.style.filter=e.style.filter.replace(/alpha\([^\)]*\)/gi,'')+'alpha(opacity='+v*100+')';}return e;})


元の関数をこれらで置換すれば依存が取れちゃいます。

ちょっと透明度を変えたいだけなのにprototype.jsとscriptaculousは大げさだなあというときに役に立ちます。

後でソースを読む人が辛くなるのでこんな感じのコメントを入れておくのも良さそうです。

var dst = {'foo':1, 'bar':2};
var src = {'foo':100};
var result = /** Object.extend */(function(d,s){for(var p in s)d[p]=s[p];return d})/**/(dst, src);


こういうセコい関数をたくさんストックしておいてコピペで使うと小さいプログラムを書くのが楽になりそうです。