JavaScript
ECMAScript
es6
ショートコーディング

JavaScript ショートコードテクニック集(ES6含む)

何の役に立つかはわからない、ショートコードのテクニック集です。
ここで紹介しているテクニックの幾つかは非推奨の記述法です。
用法、用量を守って正しくお使いください。

基本

改行と半角スペースをなくす。

before
var a = 1,
    b = 2;
console.log( a, b );
after
var a=1,b=2;console.log(a,b);

varとaの間の半角スペースなど、なくすと意味が変わってしまう部分は取れない。

変数宣言(var)を省略

before
var a = 1,
    b = 2;
after
a=1,b=2;

変数の値が同じ場合まとめる

before
var a=1,
    b=1;
after
var a=b=1;

値や計算の省略

小数点の省略

before
console.log(1+0.5);
after
console.log(1+.5);
console.log
1.5

下三桁以上が0の場合指数で表現

before
console.log(1000);
after
console.log(1e3);
console.log
1000

三桁以上でないと効果なし。
例えば、1日をミリ秒に直すと86400000だが、これは864e5と表記すれば3文字節約できる。
また小数点の場合、四桁から効果がある。

console.log(0.0001); // 6文字
console.log(.0001);  // 5文字
console.log(1e-4);   // 4文字
console.log
0.0001

小数点の切捨てはビット演算で行う

before
console.log(Math.floor(1.2345));
after
console.log(1.2345|0);
after
console.log(~~1.2345);
console.log
1

四捨五入もビット演算で行う

after
a=Math.round(10.3);
b=Math.round(10.6);
console.log(a,b);
after
a=10.3+.5|0;
b=10.6+.5|0;
console.log(a,b);
console.log
 10 11

0.5を足してビット演算をすれば四捨五入した整数値を得られる。

2の階乗をビットシフトで行う

before
console.log(131072);
after
console.log(1<<17);
console.log
131072

2の17乗以上でないと効果なし。

-1判定をビット演算で行う

例えばindexOfメソッドで条件判定を行うとき、下記のように−1と比較することになるが

before
z='abcdefg';
if(z.indexOf('a')!==-1){
  console.log('a in z');
} else {
  console.log('a not in z');
}
// 'a in z'

ビット指定演算子~で−1のみをfalse判定にすることができる

after
z='abcdefg';
if(~z.indexOf('a')){
  console.log('a in z');
} else {
  console.log('a not in z');
}
// 'a in z'

これは-10のビット反転(符号を含めて1で埋まっている状態)だからで、条件式では0以外の数値型が(負数も含めて)全てtrue判定になるからである。

逆に−1のみをtrueにしたい場合は!~z.indexOf('a')などにする。
−1を返すメソッドとして、indexOfの他にlastIndexOf、search、findIndexなどがある。

ゼロパディング

桁の合わない数字のゼロパディング(少ない桁を'0'で埋める)を行う場合、
望む桁数から1引いた数の'0'文字列(例えば、3桁を得たい場合'00')を数字の頭に足し、
slice()を使って末尾からトリミングする方法が取れます。

a=1;
a=('00'+a).slice(-3);
console.log(a);
console.log
'001'

ただし、2桁を得る場合のみ、三項演算子が一番短くなります。

2桁のゼロパディング
a=1;

// if文の場合、15文字
if(a<10)a='0'+a;

// 三項演算子の場合、14文字
a=a<10?'0'+a:a;

// sliceの場合、19文字
a=('0'+a).slice(-2);
3桁のゼロパディング
a=1;

// 三項演算子の場合、27文字
a=a<10?'00'+a:a<100?'0'+a:a;

// sliceの場合、20文字
a=('00'+a).slice(-3);

さらにES2017ではパディング用のメソッドpadStart()が用意されていますが、ショートコード観点で言うと6桁以上でないと効果がありません。

6桁のゼロパディング
a=1;

// sliceの場合、23文字
a=('00000'+a).slice(-6);

// padStartの場合、22文字
a=(''+a).padStart(6,0);

また、年月日、時分秒などの数字混じり文字列に対するゼロパディングについてはreplace()で行う方法があります。

a='2017/4/5';
a=a.replace(/(\D)(\d)(?=\D|$)/g,"$10$2");
console.log(a)
console.log
"2017/04/05"

置換処理の部分については3桁以上の場合は後方参照ではなく関数で処理した方が短くなります。

true/falseを!0/!1で代用する

before
console.log(true,false);
after
console.log(!0,!1);
console.log
 true false

論理否定演算子(!)が後に続く0や1を評価するため、結果としてtrue,falseが得られます。

配列型のように文字列から一文字を抜き出す。

before
console.log('あいうえお'.charAt(2));
after
console.log('あいうえお'[2]);
console.log
'う'

文字列を配列化する場合、区切り文字に数字を使う。

before
var a='abc,def,ghi,jkl,mno';
console.log(a.split(','));
after
var a='abc0def0ghi0jkl0mno';
console.log(a.split(0));
console.log
 ["abc", "def", "ghi", "jkl", "mno"]

この方法は配列のショートコード化にも利用でき、

before
a=['aa','bb','cc','dd','ee'];
console.log(a)
after
a='aa0bb0cc0dd0ee'.split(0);
console.log(a)
console.log
["a", "b", "c", "d", "e"]

5個以上の文字列の配列であれば、一つの文字列をsplitで分けたほうが文字数を削減できます。

また、文字列を一文字ずつ配列に格納したい場合、

before
a='abcdefg'.split('');
console.log(a);
before
a=[...'abcdefg'];
console.log(a);
console.log
[ "a", "b", "c", "d", "e", "f", "g" ]

es6のスプレッド構文ならばsplitメソッドを使うより、文字数を削減できます。

同じ文字の繰り返しを作る場合、repeat()を使う。(ES6)

before
console.log('aaaaaaaaaaaaaa');
after
console.log('a'.repeat(13));
console.log
'aaaaaaaaaaaaaa'

n回の繰り返し文字列を得たい場合、repeat()を使う。13文字以上でないと効果なし。
ただしrepeat()は現在Firefoxのみ対応なので、

after
console.log(Array(17).join`a`);

n+1の配列を作り繰り返したい文字列でjoinする方法を使う。
この方法は16文字以上でないと効果なし。

乱数生成にDateを利用する

before
console.log(Math.random()*2&1);
after
console.log(new Date&1);
console.log
// 0か1の乱数を生成する

ミリ秒を返すDateは乱数の代わりとして利用できる。

配列の値の取り出しに分割代入を使う(ES6)

before
a=0;
b=0;
c=[1,[2,3,4],5];
a=c[0];
b=c[1][0];
console.log(a,b);
after
a=0;
b=0;
c=[1,[2,3,4],5];
[a]=c;
[,[b]]=c;
console.log(a,b);
console.log
1 2

配列の0番目へのアクセスに分割代入を利用すれば(1文字分だけだが)ショートコード化することができる。
これは文字列に対しても有効。

after
a='';
b='xyz';
[a]=b;
console.log(a);
// -> 'x'

配列のコピーにスプレッド構文を使う(ES6)

before
a=[1, 2, 3];
b=a.slice(); // 11文字
b.push(4);
console.log(a, b);
after
a=[1, 2, 3];
[...b]=a; // 8文字
b.push(4);
console.log(a, b);
console.log
[ 1, 2, 3 ] [ 1, 2, 3, 4 ]

スプレッド演算子を使えばslice()を使うより短く配列コピーを実現できます。

配列やオブジェクトの連結にスプレッド構文を使う(ES6)

before
a=[1,2,3],b=[4,5,6];
a.push.apply(a,b);
console.log(a);
after
a=[1,2,3],b=[4,5,6];
a.push(...b);
console.log(a);
after
a=[1,2,3],b=[4,5,6];
console.log([...a,...b]);
console.log
[1, 2, 3, 4, 5, 6]

スプレッド構文を使えば配列やオブジェクトを分割して代入できます。
また同じ方法でオブジェクトのマージも可能です。

before
a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c=Object.assign(a,b) // 18文字
console.log(c)
after
a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c={...a,...b} // 11文字
console.log(c)
console.log
{ z1: 1, z2: 4, z3: 5, z4: 6 }

配列の先頭を削る(ES6)

before
a=[1,2,3,4,5,6];
b=a.slice(1);
console.log(b);
after
a=[1,2,3,4,5,6];
[,...b]=a;
console.log(b);
console.log
[2, 3, 4, 5, 6]

スプレッド構文を使ってbを可変長にすることで配列の先頭を削った配列を返します(カンマを繰り返して複数削ることも可能)。ただしこの方法は後尾から配列を削る応用はできません。

16進数文字列の10進数化の省略

before
a='10';
console.log(parseInt('10',16));
after
a='10';
console.log('0x'+a-0);
console.log
16

最後に数値型0を計算することで全体を数値型に変換し、結果として10進数になります。
また2進数なら「0b」、8進数なら「0o」で変換できます。

オブジェクトやメソッドなどの省略

window オブジェクトをthisで取得

before
console.log(window);
after
console.log(this);
console.log
Window

グローバルにおけるthisはwindowオブジェクトを示すので、thisに変えれば2文字省略できる。

document.getElementByIdの省略

html
<div id="t">this is test.</div>
before
console.log(document.getElementById('t').innerText);
after
console.log(t.innerText);
console.log
"this is test."

HTMLに指定したidはオブジェクトとして直接指定することができる。
document.bodyなども、bodyタグにidを指定することができれば、直接指定できる。

new演算子の対象のカッコを省略する

before
console.log(new Date());
console.log(new Array());
after
console.log(new Date);
console.log(new Array);
console.log
//現在時刻
[]

new演算子の対象とするオブジェクトの場合、カッコ()を省略することができる。

繰り返し使うメソッドやオブジェクトを変数に格納する。

before
console.log(Math.ceil(12.5),Math.ceil(0.2));
after
a=Math.ceil;
console.log(a(12.5),a(0.2));
console.log
13 1

メソッドに配列でアクセスする

before
test1.classList.add('a');
test2.classList.add('b');
test3.classList.add('c');
after
test1[x='classList'][y='add']('a');
test2[x][y]('b');
test3[x][y]('c');
console.log
// それぞれの要素にクラスを付加する

setTimeout、setIntervalの第一引数を文字列で渡す

before
setTimeout(function(){
    console.log('あ');
},1000);
after
setTimeout("console.log('あ')",1000);
console.log
'あ'

setTimeout、setIntervalはeval()のように文字列をコードとして評価することができる(evalと同じく非推奨)。さらに時間が1ミリ秒であれば第二引数を省略できる。

after
setTimeout("console.log('あ')");

ES6ならさらに省略できる

after
setTimeout`console.log('あ')`;

文字列を渡すメソッドの()を省略する(ES6)

before
alert('あ');
after
alert`あ`;

クォーテーションではなくバックティック(` `)で渡すことでパーレンを省略できる。

ステートメントの省略

if文の省略

else節の無いif文を論理演算子で代用する

before
a='あ';
if(a=='あ'){
    console.log(a+a);
}
after
a='あ';
(a=='あ')&&console.log(a+a);
console.log
'ああ'

AND(&&)は左辺がtrueの場合右辺を評価し、左辺がfalseの場合右辺を評価しないのでif文の代用として使用できる。

before
a=0;
if(!a){
    console.log(a);
}
after
a=0;
a||console.log(a);
console.log
0

条件に否定演算子を使っている場合はOR(||)を使います。||は左辺がtrueの場合右辺を評価せず、左辺がfalseの場合右辺を評価します。

if...else文を三項演算子に書き換える。

before
var a=1,b=2,c;
if(a==1){
    c=a+b;
} else {
    c=a-b;
}
console.log(c);
after
var a=1,b=2,c;
c=(a==1)?a+b:a-b;
console.log(c);
console.log
3

「条件?処理:条件?処理:処理」のように書けば、else ifも表現することができる。

for文の省略

ブレースを省略する

before
a=b=0;
for(var i=0;i<10;i++){
    a+=i;
    b+=i;
}
console.log(a,b);
after
a=b=0;
for(var i=0;i<10;i++)a+=i,b+=i;
console.log(a,b);
console.log
45 45

ブレースを省略できるのはステートメントが一つの場合だが、カンマ演算子を使えば単一ステートメントとして処理できる。

デクリメントで記述し条件式を省略する

before
a=b=0;
for(var i=0;i<10;i++){
    a+=i;
    b+=i;
}
console.log(a,b);
after
a=b=0;
for(var i=10;i--;){
    a+=i;
    b+=i;
}
console.log(a,b);
console.log
45 45

条件式と変化式が一緒になるので、iがfalse(つまり0)になるとループが終了する。

for文のネストを省略する

before
for(i=10;i--;)for(j=5;j--;)console.log(i,j);
after
for(k=50;k--;)console.log(k/5|0,k%5);

iとjを掛けた数だけループさせ、元iの値はk/jを切り捨てた数、元jの値はk/jの剰余を使う。

switch文の省略

jQueryを使って矢印キー「←、→」などに処理を行いたい場合、

before
$(document).on('keypress', function(e){
    switch (e.keyCode){
        case 39:
            console.log('next');
            break;
        case 37:
            console.log('prev');
            break;
        default:
            break;
    }
});
after
$(document).on('keypress', function(e){
    (b=({39:'next',37:'prev'})[e.keyCode])&&console.log(b);
});
console.log
「←」を押すと'prev'、「→」を押すと'next'が出力され、それ以外のキーは無視する

連想配列を利用した出し分け。if文の省略(上記)や代入を処理文の中に書く方法(下記)を併用し、指定以外のキーを無視している。

代入を処理文の中に書く

before
mes='あ';
console.log(mes);
after
console.log(mes='あ');
console.log
'あ'
before
a=1,b=2;
c=a+b;
console.log(c);
after
c=(a=1)+(b=2);
console.log(c);
console.log
3

Template literalを使い文字列操作を省略する(ES6)

before
a='い',b='う';
console.log('あ'+a+b+'え\nお');
after
a='い',b='う';
console.log(`あ${a+b}え
お`);
console.log
'あいうえお'

バックティック(` `) で囲むES6のTemplate literalは、文字列の中にプレースホルダー「${~}」で式や変数を挿入できるため、場合によってはショートコード化に役立つ。また改行もそのまま書けるため、エスケープ文字で書くより文字数を削減できる。

配列、オブジェクトの初期化

before
var a = new Array(),
    b = new Object;
console.log(a,b);
after
var a=[],b={};
console.log(a,b);
console.log
[] Object {}

配列はブラケット([])、オブジェクトはブレース({})で初期化できる。

functionをアロー関数で記述し省略する。(ES6)

before
var a = function(r){
    return 'あ'+r;
};
console.log(a('い'));
after
var a=(r)=>{return 'あ'+r};
console.log(a('い'));
console.log
'あい'

ES6のアロー関数式は従来と比べ文字数を大幅に削減できる。

after
var a=r=>'あ'+r;
console.log(a('い'));

引数が一つだけならパーレンを省略できる(引数を使わない場合は反対に省略できず、「a=()=>~」と書くことになるので使わなくても引数を入れたほうが文字数は減らせる)。またアロー関数を式として使う場合はreturnを省略でき、関数内の式が一つであればブレースも省略できる。