2014年06月28日

実用的?変態的!?JavaScriptの実用的なショートコーディングをまとめてみた

最近、自分がブログを作っていたということを思い出したので、ちょいちょい書いていこうと思います(しろめ

さてさて、今回はJavaScript特有の気持ち悪い記法と、その説明についてまとめたいと思います。
これを読めば、他人の書いた闇術式特殊なJSコーディングが読めるかもしれません。

一部「その書き方、ほかの言語でも出来るよ!」ってのはありますが、基本的には(いい意味かはおいといて)JSっぽい書き方のみを紹介していきたいと思います。

ちなみに若干タイトル詐欺あります。お気をつけ下さい。


初級編

・配列、オブジェクトの省略記法

//before
var hogeArray = new Array();
var poyoObject = new Object();
//after
var hogeArray = [];
var poyoObject = {};
っていうかこれは流石にほとんどの方がしますよね?
大括弧閉じは配列を意味し、中括弧閉じはオブジェクトを意味する省略記法です。

ちなみに、new Array(num);の書き方では、numに値を指定すると、undefinedで初期化した、長さnumの配列を作ることが出来ます。これは大括弧の省略記法では出来ないです。


・数値⇔文字列キャスト

//before
var numToString = (18).toString();
var stringToNum = parseInt("18",10);
//after
var numToString = 18 + "";
var stringToNum = "18" - 0;
これもそこそこ有名ですね。
前者は、数値を文字列と結合すると、全体が文字列になる性質を利用して、
""(空文字)を足して数値から文字列へのキャストです。
後者は、文字列から数値を引くと、全体が数値になる性質を利用して、
0を引いて文字列から数値へのキャストです。


中級編
・配列列挙

//before
console.log("配列arrを逆順列挙でしたい時");
for(var i=arr.length-1;i>=0;i--){
console.log(arr[i]);
}
//after
console.log("配列arrを逆順列挙でしたい時");
for(var i=arr.length;i--;){
console.log(arr[i]);
}
配列を逆順(もしくは順不同)で列挙したい場合は、i--の性質を利用すれば、文字数を大幅に減らすことが可能です。
JSにおいて、Numberの「0」はfalse、「0以外の数値」はtrueを返すので、i--によって、iの値が0になるまでの間、ループを行い、結果的に逆順列挙が可能です。

おいおい、ちょっと待って欲しい。
どうしても昇順列挙したいときはどうするんだよって思いますよね?安心してください、その例も示します。

//before
console.log("配列arrを昇順列挙でしたい時");
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
}
//after
console.log("配列arrを昇順列挙でしたい時");
for(var i=0;arr[i];i++){
console.log(arr[i]);
}
//extra
console.log("配列arrを昇順列挙でしたい時");
for(var i=0,iLen=arr.length;i<iLen;++i){
console.log(arr[i]);
}
afterに示した方法ではarr[i]がout of rangeに達すると、「undefined」を返すというJSの配列の性質を利用して、終了条件を求めます。
undefinedはfalseを意味するので、結果的に昇順列挙が可能です。

が、しかしarr[i]を列挙している最中に、falseを意味する「0」や「""(空文字)」や「null」や「false」等々が含まれていた場合、そこでループが終わってしまうので注意してください。

extraでは、おまけで汎用的に高速な昇順列挙を示しました。beforeよりもタイプ数が増えていますが、arrの中のlengthというプロパティに毎回毎回参照するのは、動作効率が非常に悪いので、事前に変数に格納しておくことで、高速化が望めます

ただし、こいつにも弱点があって、for文中に、arrに対して破壊的な処理(pushとかpopとか)を行っても、長さを格納したiLenの値は変わりません。
したがって、ループ中に配列長さが変化する場合には注意してください

結論:for文に関しては一長一短ありますので臨機応変に切り替えましょう。


・if-else if-else if-...(ry

//before
if(hoge == ○○){
}
else if(poyo == ××){
}
else if(huga == □□){
}
...(ry
//after
switch(true){
case hoge == ○○ :
break;
case poyo == ×× :
break;
case huga == □□ :
break;
...(ry
}
switch(true)を使えば、if-else ifを大量に使った読みづらいコードが、劇的に読みやすくなります。
ただ、こいつに関しては、読みやすいという点以外にメリットはない
タイプ数は無駄に増えるし、ショートコーディングをメインとする今回の趣旨にはあまり合わな...うわ何するやめろ!!!


上級編
・無名関数即時実行

//before
var res = (function(){
console.log("がおさんじゅうはっさい");
return 18;
})();
console.log(res); //18
//after
var res = !function(){
console.log("がおさんじゅうはっさい");
return 18;
}();
console.log(res); //false
無名関数の先頭に、論理否定を表す「!」を使用することで、関数全体をカッコで挟むこと無く無名関数の即時実行が可能になります。1文字減りました!(コードゴルフかっw

なお当然のことですが、この関数が戻り値をもつ場合、論理を反転してbool型にしてしまうのでその点のみ注意です。


・切り捨て

//before
var num = Math.floor(Math.random()*10);
console.log(num); //0~9の整数値
//after
var num = Math.random()*10 | 0;
console.log(num); //0~9の整数値
ビット演算を行う際に、対象となる数が整数値でない場合、「その値を切り捨てて整数にした後、演算を行う」という仕様があります。
その性質を利用し、「0とビット和を取るという無意味な行為」すると切り捨てが可能です。

しかし、注意していただきたいのは、JSのビット演算は「32bitのint型(>>>演算だけは例外的に32bitのunsigned int)」の範囲内で演算を行います。
莫大に大きい数値の切り捨てにはMath.floor()を使ってください。


・文字列検索

//before
if(str.indexOf("18")!=0){
console.log("変数strの中には「18」という文字が含まれています");
}
//after
if(~str.indexOf("18")){
console.log("変数strの中には「18」という文字が含まれています");
}
indexOfは、文字列が含まれていた時は文字のHITした位置を0以上の数値を返します。HITしなければ-1を返します。
ビット反転を表す「~」を、-1に使用すると、2進数で「1111111...(ry」だったものが「0000000...(ry」に変わるので、値としては0になります。

0はfalse、0以外はtrueなので結果的にHITしたかどうかの判定が可能です。




さて、いかがだったでしょうか。知ってるものばかりでした?でしたら立派なJSerです!!

JSは独特な気持ち悪い可愛いコーディングがいくつかありますが、マスターするととても書きやすい言語になります!ぜひぜひ、いろんな書き方を学びましょうっ
posted by がお at 01:58| Comment(0) | Javascript | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

×

この広告は1年以上新しい記事の投稿がないブログに表示されております。