LoginSignup
214
247

More than 1 year has passed since last update.

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

Last updated at Posted at 2016-07-28

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

基本

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

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 = 1;
after
a=b=2;

値や計算の省略

小数点の省略

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を足してビット演算をすれば四捨五入した整数値を得られる。

べき乗をべき乗演算子で行う(ES6)

before
console.log(Math.pow(-3,2));
after
console.log(-3**2);
console.log
9

べき乗演算子**が実装されたのでMath.powを使うより断然短くなる。

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などがある。

文字列型から数値型への変換

before
var a = '123456';
parseInt(a) // 11文字
Number(a) // 9文字
after
var a = '123456';
+a // 2文字

数値型から文字列型への変換

before
var a = 123456;
a.toString() // 12文字
String(a) // 9文字
after
var a = '123456';
a+'' // 4文字

ゼロパディング

桁の合わない数字のゼロパディング(少ない桁を'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文字以上でないと効果なし。

また、配列のままで良い場合はfill()メソッドが使える。(ES6)

after
console.log(Array(17).fill('a'));

乱数生成に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」で変換できます。

配列数の評価にlengthプロパティではなくin演算子を使う

before
a=[1,2,3];
console.log(a.length>3); // 10文字
after
a=[1,2,3];
console.log(3 in a); // 6文字
console.log
false

Arrayオブジェクトの場合in演算子によってインデックスが存在するかを検査でき、lengthプロパティを使うより文字数を少なくできる。

文字列の場合はin演算子を使えないが(文字列オブジェクトにすれば別)、直接アクセスすることでlengthを使わない方法で文字数を評価できる。

before
a='xyz';
console.log(a.length>3); // 10文字
after
a='xyz';
console.log(!!a[3]); // 6文字
console.log
false

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

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

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

グローバルにおけるthisはwindowオブジェクトを示す(Node.jsにおいてはglobal)ので、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

頻出するオブジェクトをwith句でまとめる

before
Math.ceil(1.5)+Math.floor(1.5)+Math.round(1.5);
after
with(Math)ceil(1.5)+floor(1.5)+round(1.5);
console.log
5

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

before
test1.classList.add('a');
test2.classList.remove('b');
test3.classList.add('c');
after
test1[x='classList'][y='add']('a');
test2[x].remove('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(''); // アラートボックスを表示する
test.classList.add('a'); // test要素にクラス名「a」を追加する
after
alert`あ`;
test.classList.add`a`

クォーテーションではなくバックティック(` `)で渡すことでパーレンを省略できる。
これはテンプレートリテラルを直接関数やメソッドに渡すと、第一引数として、文字列を返すことを利用したもの(したがって第2引数まで利用するような処理の場合はエラーが発生する恐れがある)。

ステートメントの省略

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も表現することができる。

型の判定

string型

before
a=0;
b='0';
// 19文字
console.log(typeof a==='string'); // false
console.log(typeof b==='string'); // true
after
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型

before
a=0;
b='0';
console.log(typeof a==='number');
console.log(typeof b==='number'); // 19文字
after
a=0;
b='0';
console.log(+a===a);
console.log(+b===b); // 6文字
console.log
true
false

boolean型

before
a=0;
b=false;
console.log(typeof a==='boolean');
console.log(typeof b==='boolean'); // 19文字
after
a=0;
b=false;
console.log(!!a===a);
console.log(!!b===b); // 7文字
console.log
false
true

undefined

before
a={b:3};
console.log(typeof a.b==='undefined');
console.log(typeof a.c==='undefined');  // 24文字
after
a={b:3};
console.log(a.b===0[0]);
console.log(a.c===0[0]); // 10文字
console.log
false
true

undefinedはundefinedになる文と比較することでtypeofの代替になる。

Infinity

before
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
after
a=0;
b=Math.pow(10, 1000);;
// 7文字
console.log(a!==1/0); // true
// 7文字
console.log(b===1/0); // true

計算結果が無限大になる計算はInfinity変数と同値となるので、結果無限大の判定に利用できる。

function型

before
b=()=>3;
// 21文字
console.log(typeof b==='function');  // true
after
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オブジェクト

before
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
after
a={foo:1};
b=[1,2,3];
// 5文字
console.log(a.pop) // undefined
console.log(b.pop) // function pop()

pop()メソッドがあるかどうかでArrayオブジェクトであるかどうかを判定できる。

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
['a','b','c','d'][x>3?3:x]
// xが3以上の場合は必ず'd'を出力する
after
['a','b','c'][x]||'d'
// xが3以上の場合は必ず'd'を出力する

代入を処理文の中に書く

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を省略でき、関数内の式が一つであればブレースも省略できる。

214
247
11

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
214
247