何の役に立つかはわからない、ショートコードのテクニック集です。
ここで紹介しているテクニックの幾つかは非推奨の記述法です。
用法、用量を守って正しくお使いください。
基本
改行と半角スペースをなくす。
var a = 1,
b = 2;
console.log( a, b );
var a=1,b=2;console.log(a,b);
varとaの間の半角スペースなど、なくすと意味が変わってしまう部分は取れない。
変数宣言(var)を省略し、変数の値が同じ場合まとめる
var a = 1,
b = 1;
a=b=2;
#値や計算の省略
小数点の省略
console.log(1+0.5);
console.log(1+.5);
1.5
下三桁以上が0の場合指数で表現
console.log(1000);
console.log(1e3);
1000
三桁以上でないと効果なし。
例えば、1日をミリ秒に直すと86400000
だが、これは864e5
と表記すれば3文字節約できる。
また小数点の場合、四桁から効果がある。
console.log(0.0001); // 6文字
console.log(.0001); // 5文字
console.log(1e-4); // 4文字
0.0001
小数点の切捨てはビット演算で行う
console.log(Math.floor(1.2345));
console.log(1.2345|0);
console.log(~~1.2345);
1
四捨五入もビット演算で行う
a=Math.round(10.3);
b=Math.round(10.6);
console.log(a,b);
a=10.3+.5|0;
b=10.6+.5|0;
console.log(a,b);
10 11
0.5を足してビット演算をすれば四捨五入した整数値を得られる。
べき乗をべき乗演算子で行う(ES6)
console.log(Math.pow(-3,2));
console.log(-3**2);
9
べき乗演算子**
が実装されたのでMath.powを使うより断然短くなる。
2の階乗をビットシフトで行う
console.log(131072);
console.log(1<<17);
131072
2の17乗以上でないと効果なし。
-1判定をビット演算で行う
例えばindexOfメソッドで条件判定を行うとき、下記のように−1と比較することになるが
z='abcdefg';
if(z.indexOf('a')!==-1){
console.log('a in z');
} else {
console.log('a not in z');
}
// 'a in z'
ビット指定演算子~
で−1のみをfalse
判定にすることができる
z='abcdefg';
if(~z.indexOf('a')){
console.log('a in z');
} else {
console.log('a not in z');
}
// 'a in z'
これは-1
が0
のビット反転(符号を含めて1で埋まっている状態)だからで、条件式では0以外の数値型が(負数も含めて)全てtrue
判定になるからである。
逆に−1のみをtrueにしたい場合は!~z.indexOf('a')
などにする。
−1を返すメソッドとして、indexOfの他にlastIndexOf、search、findIndexなどがある。
文字列型から数値型への変換
var a = '123456';
parseInt(a) // 11文字
Number(a) // 9文字
var a = '123456';
+a // 2文字
数値型から文字列型への変換
var a = 123456;
a.toString() // 12文字
String(a) // 9文字
var a = '123456';
a+'' // 4文字
ゼロパディング
桁の合わない数字のゼロパディング(少ない桁を'0'で埋める)を行う場合、
望む桁数から1引いた数の'0'文字列(例えば、3桁を得たい場合'00'
)を数字の頭に足し、
slice()
を使って末尾からトリミングする方法が取れます。
a=1;
a=('00'+a).slice(-3);
console.log(a);
'001'
ただし、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);
a=1;
// 三項演算子の場合、27文字
a=a<10?'00'+a:a<100?'0'+a:a;
// sliceの場合、20文字
a=('00'+a).slice(-3);
さらにES2017ではパディング用のメソッドpadStart()
が用意されていますが、ショートコード観点で言うと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)
"2017/04/05"
置換処理の部分については3桁以上の場合は後方参照ではなく関数で処理した方が短くなります。
true/falseを!0/!1で代用する
console.log(true,false);
console.log(!0,!1);
true false
論理否定演算子(!)が後に続く0や1を評価するため、結果としてtrue,falseが得られます。
配列型のように文字列から一文字を抜き出す。
console.log('あいうえお'.charAt(2));
console.log('あいうえお'[2]);
'う'
文字列を配列化する場合、区切り文字に数字を使う。
var a='abc,def,ghi,jkl,mno';
console.log(a.split(','));
var a='abc0def0ghi0jkl0mno';
console.log(a.split(0));
["abc", "def", "ghi", "jkl", "mno"]
この方法は配列のショートコード化にも利用でき、
a=['aa','bb','cc','dd','ee'];
console.log(a)
a='aa0bb0cc0dd0ee'.split(0);
console.log(a)
["a", "b", "c", "d", "e"]
5個以上の文字列の配列であれば、一つの文字列をsplitで分けたほうが文字数を削減できます。
また、文字列を一文字ずつ配列に格納したい場合、
a='abcdefg'.split('');
console.log(a);
a=[...'abcdefg'];
console.log(a);
[ "a", "b", "c", "d", "e", "f", "g" ]
es6のスプレッド構文ならばsplitメソッドを使うより、文字数を削減できます。
同じ文字の繰り返しを作る場合、repeat()を使う。(ES6)
console.log('aaaaaaaaaaaaaa');
console.log('a'.repeat(13));
'aaaaaaaaaaaaaa'
n回の繰り返し文字列を得たい場合、repeat()を使う。13文字以上でないと効果なし。
ただしrepeat()は現在Firefoxのみ対応なので、
console.log(Array(17).join`a`);
n+1の配列を作り繰り返したい文字列でjoinする方法を使う。
この方法は16文字以上でないと効果なし。
また、配列のままで良い場合はfill()メソッドが使える。(ES6)
console.log(Array(17).fill('a'));
乱数生成にDateを利用する
console.log(Math.random()*2&1);
console.log(new Date&1);
// 0か1の乱数を生成する
ミリ秒を返すDateは乱数の代わりとして利用できる。
配列の値の取り出しに分割代入を使う(ES6)
a=0;
b=0;
c=[1,[2,3,4],5];
a=c[0];
b=c[1][0];
console.log(a,b);
a=0;
b=0;
c=[1,[2,3,4],5];
[a]=c;
[,[b]]=c;
console.log(a,b);
1 2
配列の0番目へのアクセスに分割代入を利用すれば(1文字分だけだが)ショートコード化することができる。
これは文字列に対しても有効。
a='';
b='xyz';
[a]=b;
console.log(a);
// -> 'x'
配列のコピーにスプレッド構文を使う(ES6)
a=[1, 2, 3];
b=a.slice(); // 11文字
b.push(4);
console.log(a, b);
a=[1, 2, 3];
[...b]=a; // 8文字
b.push(4);
console.log(a, b);
[ 1, 2, 3 ] [ 1, 2, 3, 4 ]
スプレッド演算子を使えばslice()を使うより短く配列コピーを実現できます。
配列やオブジェクトの連結にスプレッド構文を使う(ES6)
a=[1,2,3],b=[4,5,6];
a.push.apply(a,b);
console.log(a);
a=[1,2,3],b=[4,5,6];
a.push(...b);
console.log(a);
a=[1,2,3],b=[4,5,6];
console.log([...a,...b]);
[1, 2, 3, 4, 5, 6]
スプレッド構文を使えば配列やオブジェクトを分割して代入できます。
また同じ方法でオブジェクトのマージも可能です。
a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c=Object.assign(a,b) // 18文字
console.log(c)
a={z1:1,z2:2,z3:3}
b={z2:4,z3:5,z4:6}
c={...a,...b} // 11文字
console.log(c)
{ z1: 1, z2: 4, z3: 5, z4: 6 }
配列の先頭を削る(ES6)
a=[1,2,3,4,5,6];
b=a.slice(1);
console.log(b);
a=[1,2,3,4,5,6];
[,...b]=a;
console.log(b);
[2, 3, 4, 5, 6]
スプレッド構文を使ってbを可変長にすることで配列の先頭を削った配列を返します(カンマを繰り返して複数削ることも可能)。ただしこの方法は後尾から配列を削る応用はできません。
16進数文字列の10進数化の省略
a='10';
console.log(parseInt('10',16));
a='10';
console.log('0x'+a-0);
16
最後に数値型0を計算することで全体を数値型に変換し、結果として10進数になります。
また2進数なら「0b」、8進数なら「0o」で変換できます。
配列数の評価にlengthプロパティではなくin演算子を使う
a=[1,2,3];
console.log(a.length>3); // 10文字
a=[1,2,3];
console.log(3 in a); // 6文字
false
Arrayオブジェクトの場合in演算子によってインデックスが存在するかを検査でき、lengthプロパティを使うより文字数を少なくできる。
文字列の場合はin演算子を使えないが(文字列オブジェクトにすれば別)、直接アクセスすることでlengthを使わない方法で文字数を評価できる。
a='xyz';
console.log(a.length>3); // 10文字
a='xyz';
console.log(!!a[3]); // 6文字
false
#オブジェクトやメソッドなどの省略
window オブジェクトをthisで取得
console.log(window);
console.log(this);
Window
グローバルにおけるthis
はwindowオブジェクトを示す(Node.jsにおいてはglobal)ので、thisに変えれば2文字省略できる。
document.getElementByIdの省略
<div id="t">this is test.</div>
console.log(document.getElementById('t').innerText);
console.log(t.innerText);
"this is test."
HTMLに指定したidはオブジェクトとして直接指定することができる。
document.body
なども、bodyタグにidを指定することができれば、直接指定できる。
new演算子の対象のカッコを省略する
console.log(new Date());
console.log(new Array());
console.log(new Date);
console.log(new Array);
//現在時刻
[]
new演算子の対象とするオブジェクトの場合、カッコ()を省略することができる。
繰り返し使うメソッドやオブジェクトを変数に格納する。
console.log(Math.ceil(12.5),Math.ceil(0.2));
a=Math.ceil;
console.log(a(12.5),a(0.2));
13 1
頻出するオブジェクトをwith句でまとめる
Math.ceil(1.5)+Math.floor(1.5)+Math.round(1.5);
with(Math)ceil(1.5)+floor(1.5)+round(1.5);
5
メソッドに配列でアクセスする
test1.classList.add('a');
test2.classList.remove('b');
test3.classList.add('c');
test1[x='classList'][y='add']('a');
test2[x].remove('b');
test3[x][y]('c');
// それぞれの要素のクラスを付加ないし削除する
setTimeout、setIntervalの第一引数を文字列で渡す
setTimeout(function(){
console.log('あ');
},1000);
setTimeout("console.log('あ')",1000);
'あ'
setTimeout、setIntervalはeval()のように文字列をコードとして評価することができる(evalと同じく非推奨)。さらに時間が1ミリ秒であれば第二引数を省略できる。
setTimeout("console.log('あ')");
ES6ならさらに省略できる
setTimeout`console.log('あ')`;
文字列を渡すメソッドや関数の()を省略する(ES6)
alert('あ'); // アラートボックスを表示する
test.classList.add('a'); // test要素にクラス名「a」を追加する
alert`あ`;
test.classList.add`a`
クォーテーションではなくバックティック(` `)で渡すことでパーレンを省略できる。
これはテンプレートリテラルを直接関数やメソッドに渡すと、第一引数として、文字列を返すことを利用したもの(したがって第2引数まで利用するような処理の場合はエラーが発生する恐れがある)。
#ステートメントの省略
if文の省略
else節の無いif文を論理演算子で代用する
a='あ';
if(a=='あ'){
console.log(a+a);
}
a='あ';
(a=='あ')&&console.log(a+a);
'ああ'
AND(&&)は左辺がtrueの場合右辺を評価し、左辺がfalseの場合右辺を評価しないのでif文の代用として使用できる。
a=0;
if(!a){
console.log(a);
}
a=0;
a||console.log(a);
0
条件に否定演算子を使っている場合はOR(||)を使います。||は左辺がtrueの場合右辺を評価せず、左辺がfalseの場合右辺を評価します。
if...else文を三項演算子に書き換える。
var a=1,b=2,c;
if(a==1){
c=a+b;
} else {
c=a-b;
}
console.log(c);
var a=1,b=2,c;
c=(a==1)?a+b:a-b;
console.log(c);
3
「条件?処理:条件?処理:処理」のように書けば、else ifも表現することができる。
型の判定
string型
a=0;
b='0';
// 19文字
console.log(typeof a==='string'); // false
console.log(typeof b==='string'); // true
a=0;
b='0';
// 8文字
console.log(''+a===a); // false
console.log(''+b===b); // true
// 5文字
console.log(a.big); // undefined
console.log(b.big); // function big()
''+a===a
の方法は強制的に文字列化して、元の変数と比べることでString型かどうかを判定している。
a.big
はString型固有のメソッドであるbig()メソッドが有効であるかを調べることで判定している。
※big()メソッドは現在非推奨であり、いつ使えなくなるかはブラウザ次第。
number型
a=0;
b='0';
console.log(typeof a==='number');
console.log(typeof b==='number'); // 19文字
a=0;
b='0';
console.log(+a===a);
console.log(+b===b); // 6文字
true
false
boolean型
a=0;
b=false;
console.log(typeof a==='boolean');
console.log(typeof b==='boolean'); // 19文字
a=0;
b=false;
console.log(!!a===a);
console.log(!!b===b); // 7文字
false
true
undefined
a={b:3};
console.log(typeof a.b==='undefined');
console.log(typeof a.c==='undefined'); // 24文字
a={b:3};
console.log(a.b===0[0]);
console.log(a.c===0[0]); // 10文字
false
true
undefinedはundefinedになる文と比較することでtypeofの代替になる。
Infinity
a=0;
b=Math.pow(10, 1000);;
// 11文字
console.log(isFinite(a)); // true
// 12文字
console.log(!isFinite(b)); // true
// 12文字
console.log(a!==Infinity); // true
// 12文字
console.log(b===Infinity); // true
a=0;
b=Math.pow(10, 1000);;
// 7文字
console.log(a!==1/0); // true
// 7文字
console.log(b===1/0); // true
計算結果が無限大になる計算はInfinity変数と同値となるので、結果無限大の判定に利用できる。
function型
b=()=>3;
// 21文字
console.log(typeof b==='function'); // true
b=()=>3;
// 19文字
console.log(/^f/.test(typeof b)); // true
// 5文字
console.log(b.call); // function call()
functionは単純に比較できないので、typeofの結果の1文字目を判定する。
b.call
はfunctionオブジェクトのcall()メソッドを返すが、functionオブジェクト以外はこれを行うとundefinedを返すので結果としてfunctionオブジェクトかどうかを判定できる。
Arrayオブジェクト
a={foo:1};
b=[1,2,3];
// 16文字
console.log(Array.isArray(a)); // false
console.log(Array.isArray(b)); // true
// 18文字
console.log(a instanceof Array); // false
console.log(b instanceof Array); // true
a={foo:1};
b=[1,2,3];
// 5文字
console.log(a.pop) // undefined
console.log(b.pop) // function pop()
pop()メソッドがあるかどうかでArrayオブジェクトであるかどうかを判定できる。
for文の省略
ブレースを省略する
a=b=0;
for(var i=0;i<10;i++){
a+=i;
b+=i;
}
console.log(a,b);
a=b=0;
for(var i=0;i<10;i++)a+=i,b+=i;
console.log(a,b);
45 45
ブレースを省略できるのはステートメントが一つの場合だが、カンマ演算子を使えば単一ステートメントとして処理できる。
デクリメントで記述し条件式を省略する
a=b=0;
for(var i=0;i<10;i++){
a+=i;
b+=i;
}
console.log(a,b);
a=b=0;
for(var i=10;i--;){
a+=i;
b+=i;
}
console.log(a,b);
45 45
条件式と変化式が一緒になるので、iがfalse(つまり0)になるとループが終了する。
for文のネストを省略する
for(i=10;i--;)for(j=5;j--;)console.log(i,j);
for(k=50;k--;)console.log(k/5|0,k%5);
iとjを掛けた数だけループさせ、元iの値はk/jを切り捨てた数、元jの値はk/jの剰余を使う。
switch文の省略
jQueryを使って矢印キー「←、→」などに処理を行いたい場合、
$(document).on('keypress', function(e){
switch (e.keyCode){
case 39:
console.log('next');
break;
case 37:
console.log('prev');
break;
default:
break;
}
});
$(document).on('keypress', function(e){
(b=({39:'next',37:'prev'})[e.keyCode])&&console.log(b);
});
「←」を押すと'prev'、「→」を押すと'next'が出力され、それ以外のキーは無視する
連想配列を利用した出し分け。if文の省略(上記)や代入を処理文の中に書く方法(下記)を併用し、指定以外のキーを無視している。
この方法は配列の例外処理などでも利用できる。
['a','b','c','d'][x>3?3:x]
// xが3以上の場合は必ず'd'を出力する
['a','b','c'][x]||'d'
// xが3以上の場合は必ず'd'を出力する
代入を処理文の中に書く
mes='あ';
console.log(mes);
console.log(mes='あ');
'あ'
a=1,b=2;
c=a+b;
console.log(c);
c=(a=1)+(b=2);
console.log(c);
3
Template literalを使い文字列操作を省略する(ES6)
a='い',b='う';
console.log('あ'+a+b+'え\nお');
a='い',b='う';
console.log(`あ${a+b}え
お`);
'あいうえお'
バックティック(` `) で囲むES6のTemplate literalは、文字列の中にプレースホルダー「${~}」で式や変数を挿入できるため、場合によってはショートコード化に役立つ。また改行もそのまま書けるため、エスケープ文字で書くより文字数を削減できる。
配列、オブジェクトの初期化
var a = new Array(),
b = new Object;
console.log(a,b);
var a=[],b={};
console.log(a,b);
[] Object {}
配列はブラケット([])、オブジェクトはブレース({})で初期化できる。
functionをアロー関数で記述し省略する。(ES6)
var a = function(r){
return 'あ'+r;
};
console.log(a('い'));
var a=(r)=>{return 'あ'+r};
console.log(a('い'));
'あい'
ES6のアロー関数式は従来と比べ文字数を大幅に削減できる。
var a=r=>'あ'+r;
console.log(a('い'));
引数が一つだけならパーレンを省略できる(引数を使わない場合は反対に省略できず、「a=()=>~」と書くことになるので使わなくても引数を入れたほうが文字数は減らせる)。またアロー関数を式として使う場合はreturnを省略でき、関数内の式が一つであればブレースも省略できる。