-->

2010-04-18

javascript を短くしてみましょう 第5回

jquery-1.4.2.min.js を三度短くしてみましょう。

javascript を圧縮するツールはすでにあるので、そちらがお勧めです。
http://fnya.cocolog-nifty.com/blog/2007/08/yui_compressor__57c4.html
http://webos-goodies.jp/archives/51182388.html
http://dogmap.jp/2007/09/06/minify-javascript/
http://fnya.cocolog-nifty.com/blog/2009/10/microsoft-ajax-.html
http://aspnet.codeplex.com/releases/view/34488

jquery-1.4.2.min5.2010-04-18.js.gz (通常時: 約 70.2KB, 圧縮時: 約 22.7KB)

jquery-1.4.2.min.js と比べて 258 Byte 縮みました。
また簡単な動作テストしかしていないです。

今回の結論は、比較的に安全な動作変更を含むサイズ最適化の修正が、残されていることがわかりました。
例えば var x=parseFloat; とすると 167 Byte 前後縮むかもしれません。

「javascript を短くしてみましょう」としての結論は、ライブラリの場合、公式サイトで配布されているjsファイルをそのまま使うのが1番良い、ということです。圧縮する場合は javascript のコーディングと圧縮ツールの選定者が同一か、関連する他者すべての同意を得て、実績のあるツールを利用する、といった処理が必要な場合があります。
また、javascriptの文法を理解する勉強にはなります。書いてある内容の意味(どうしてそう書いてあるのか)の勉強には(少ししか)なりません。

今回の javascript を短くする方法は、前回に利用した方法を利用しています。
×の部分は反映されていませんので不可能であるかもしれません。
○ ライセンスを除くコメントの削除。
○ ローカルな変数、関数名の変更。
○ スペース(文法的なワーニングを含む、動作の変更を含まない)の削除。
○ セミコロン(文法的なワーニングを含む、動作の変更を含まない)の削除。
× グローバルな変数、関数名を沢山利用されている場合にローカル変数に代入して置き換える。
× var a; var b; を var a, b; にする。(連続するvar宣言をまとめる) 追記: function(){for(var i=0;i<xxx;i++){}var j=0;for(var k in xxx){}} → function(){var i,j,k; ...}
× if(xxx){yyy} を if(xxx)yyy; にする。({...}の中の処理が単独な場合{}を消す)
× function xxx(){...}; のセミコロンを消す。(処理が無いセミコロンを消す)
× 到達することが無いifブロックなどを消すということをする機能がツールによってはあるそうです。

また jquery を使う場合 click, getWH, k, i という名前はグローバルな変数、関数名に使わない方がいいかもしれません。
click, k
d.attachEvent("onclick",function k(){ ... d.detachEvent("onclick",k)});

getWH, i
function i(){e=b=== ... ==0?i():c.swap(a,ob,i);
追記: 変数(関数名)のスコープの判定が間違っていました。下記の場合にxxx()がグローバルな関数ではないことが明確であることを判断できていないです。
function () { ... if (...) { ... function xxx(){ ... } ... xxx() ... } ... }
function () { ... if (...) { ... function xxx(){ ... xxx() ... } ... } ... }

「javascript を短くしてみましょう」で利用したツールは下記になります。
javascript パーサ
SpiderMonkey jsparsenodetree 他には ECMAScript パーサ で探すと良いのがあるかもしれません。
全体的な処理
php コマンド (5.2.13-pl0-gentoo) パース結果のツリー構造のデータの処理や、検証のための別のアプローチの処理(例:pcreの正規表現)で利用します。 好きな言語であれば何でも良いはずです。
圧縮
gzip コマンド (1.4) phpのgzip関数より結果が良いため利用しています。

「javascript を短くしてみましょう」のツールのphp部分の作成の流れは下記になります。
(1)
javascriptの完全に把握している1KB~5KBの短いファイルを用意します。
(2)
(1)のツリー構造のデータを元に、コメントやスペースを削除するだけの処理を作成します。
(3)
1文字ずつ読むか、正規表現か、得意な方で(2)と同じ処理を作成します。ツリー構造のデータを扱うのに慣れている場合で、かつ、ECMAScript系に詳しい場合は任意です。
(4)
(2),(3)が同じ内容になるまで、修正します。動くことを確認します。
(5)
変数を短くしたりする機能を(2)に追加します。その際(3)と同じ出力をできる機能を残します。(3)自体に機能を追加するのは大変なので諦めます。
(6)
(1)のファイルを別のファイルにして(2)~(5)を繰り返します。 別ファイルの候補は、ある程度長く、いろいろな書き方で記述されているファイルを2つ以上です。
(7)
一通りできたところでjavascriptを出力する直前のデータがあると思うので、変数名を入れ替える処理を追加して圧縮率を上げます。 ...A... より ...B... の方が圧縮した際に短くなる場合がある、という処理の連続です。この処理は任意です。例えばjqueryの場合1.5~2時間かかります。gzipのアルゴリズムの知識のある場合、もっと早く、小さくできるのかもしれません。

追記: ...(3)自体に機能を追加するのは大変なので諦めます。...の部分の例です。
// (a), (b), (c), (d) は b と名乗る関数の場所
// (1), (2), (3), (4) は外側の b ではない b を定義した場合

str = "";
function b(){str = "" + str + 1;}                         //     (a)
function a(c) {
    b();                                                  //     (b)
    //if (c==1){var b = function (){str = "" + str + 2;}} // (1) (c)
    //if (c==1){function b(){str = "" + str + 3;}}        // (2) (c)
    //{function b(){str = "" + str + 4;}}                 // (3) (c)
    //function b(){str = "" + str + 5;}                   // (4) (c)
    b();                                                  //     (d)
}
a(1);
a(2);
alert(str);

// 無し: 1111                 (a,b,c,d) 全て同じ名前で(a)に合わせる。
// (1) : b is not a function
// (2) : 1311                 (a,b,c,d) 全て同じ名前で(a)に合わせる。
// (3) : 1414                 (a,b) (c,d) がそれぞれ同じ名前
// (4) : 5555                 (b,c,d) が同じ名前で (a)は無関係
結局のところ、ツリー構造か、似たデータを作成するようになるかもしれないので、であれば、最初からツリー構造のデータが欲しいと思うかもしれません。
jquery-1.4.2.min5.2010-04-18.js.gz の場合(4)以外の例ではbをすべてグローバル変数として扱っています。よって、変数名の縮小の対象外になっています。しかし該当する部分が k,i と元から短いです。
よって function b(){} を function の中の function 以外の {...} の中に書く場合は function a(c) { var b; ... } とすると、変数(関数)のスコープが明確です。

javascript を短くしてみましょう 第1回
javascript を短くしてみましょう 第2回
javascript を短くしてみましょう 第3回
javascript を短くしてみましょう 第4回

0 件のコメント: