Edited at

「可読性を上げる」ために敢えてショートハンドを使う


対象


  • JavaScript 初心者

  • キーを叩きすぎて手が痛くなってしまった人

  • めんどくさがりの人


tl;dr


  • コードゴルフにおいてショートハンドがよくつかわれますが、
    ここでは可読性が高く、かつ文字数を少なくすることができるショートハンドを紹介します。

  • もちろん可読性が高いというのは、人によって基準が異なるので、ここで紹介するのはあくまでも個人的なものです。

  • 使いすぎてはいけません。コーディング規約があればそれを遵守しましょう。


条件分岐


ifの省略 (三項演算子)


before

const month = 5;

if (month >= 5) {
console.log("令和で、あります。");
} else {
console.log("平成で、あります。");
}



after

console.log(`${ month >= 5 ? "令和" : "平成" }で、あります。`);



ifの省略 (And演算子)


before

const isReiwa = true;

if (isReiwa) {
console.log("令和で、あります");
}



after

const isReiwa = true;

isReiwa && console.log("令和で、あります");


&& の左側が truthy と判定されるときに右側が実行される。


エルビス演算子やNull合体演算子の代わり

let v1 = "yeah!!!"

let v2;
console.log(v1 || "default"); //> "yeah!!!"
console.log(v2 || "default"); //> "default"

※注: 厳密には左側が falsy に判定される場合に右側が返される。


falsy と判定される


  • false

  • ""

  • NaN

  • 0

  • undefined

  • null

(truthy については上記以外)

そのため、次のような場合正常な動作が見込めない:

function rotate180(angle) {

// デフォルトで 90 をセット…???
angle = angle || 90;

const rotatedAngle = angle + 180;

if(rotatedAngle <= 360) {
return rotatedAngle;
} else {
return rotatedAngle - 360;
}
}

寒気がしますね(これは書かないと思いますが)。

このコードでの問題点は、angle0 が渡されたとき、

次のように解釈されるからです。

/* 1 */ angle = angle || 90

/* 2 */ angle = 0 || 90 // 右側から評価を始める
/* 3 */ angle = false || 90 // `0` は `falsy`
/* 4 */ angle = 90 // 評価が右側に移る

つまり、 0 がセットできない ということです!!!

このような場合は、 パラメータの初期値 のセットを使いましょう。


ループ ※追記

@pxfnc さんより追記

for文で配列の全ての要素にアクセスして何かするパターンにおいて、for(~ of ~)forEachメソッドを使うと漏れがなくループさせることができます。


before

const items = ["foo", "bar", "baz"]

for(let i = 0; i < items.length; ++i) {
console.log(items[i])
}


これは以下のように変更できます


after(for~of)

const items = ["foo", "bar", "baz"]

for(const item of items) {
console.log(item)
}



after(forEach)

const items = ["foo", "bar", "baz"]

items.forEach(item => console.log(item))


要素にアクセスする[i]を忘れるミスだったり、forの条件の書き方を間違えたりループ内でiに代入したりするミスによって無限ループしたり全ての要素にアクセスできなかったりするという地獄から解放されます。ついでにタイプ数が少ないので指が痛くなりません。


関数


アロー関数


before

const doSomething = function(input) {

return input - 2018;
};


phase1


after-phase1

const doSometing = (input) => {

return input - 2018;
};

function式アロー関数 は完全に同じではありません。

(this が束縛されない・prototypeがない…)

パフォーマンス等によってアロー関数のほうが優れている場合があります。


phase2 (引数、処理部分のかっこを省略)


after-phase2

const doSomething = input => input - 2018;


アロー関数では、


  • 引数が1つしかない場合、引数を囲むかっこ(丸括弧・パーレン)を

  • 処理と返り値が等しい場合、処理部分を囲むかっこ(波括弧・ブレース)を

省略することができます。


パラメータの初期値


before

function squareArea(width, height) {

if(width === undefined) {
width = 10;
}
if(height === undefined) {
height = 5;
}
return width * height;
}


after

const squareArea = (width = 10, height = 5) => width * height;


= 10, = 5 部分でデフォルト値を指定できます。

逆に必須にして、エラーを投げたいときは、

const errorThrower = () => {

throw new Error();
}

const squareArea = (width = 10, height = errorThrower()) => width * height;


パラメータをオブジェクトで受け取って変数に展開

@yuta0801 さんより追記


before

const func1 = obj => {

const a = obj.a;
const b = obj.b;
const c = obj.xxx.c;

// do something...
}



after

const func2 = ({a, b, xxx: {c}}) => {

// do something...
console.log(a, b, c);
}

func2({
a: "aaa!",
b: "bbb!",
xxx: {
c: "ccc!"
}
}) //> "aaa!" "bbb!" "ccc!"


標準のJavaScriptの関数の返り値から取り出したリ、

APIを叩いてデータを取得するときにも使えます。

初期値もセットできます。


返り値について返す前に処理


before

const func = num => {

num += 1;
return num;
}


after

const func1 = num => ++num;

const func2 = num => (num+=1, num);


代入演算子

代入演算子は、変数に計算結果を代入するが、

同時に、式の値としても計算結果を返す。

let num = 10;

console.log(num += 5); //> 15
console.log(num); //> 15

+= -= *= /= %= **=


インクリメント・デクリメント、前置・後置



  • 後置 なら加算/減算 の値を返す。


  • 前置 なら加算/減算 の値を返す。


カンマ演算子

複数の式を評価して、最後の結果を返す。

説明は割愛したいと思う。


数値


10の累乗

一、十、百、千、万、十万、、、

1e0 === 1

1e1 === 10
1e2 === 100
1e3 === 1000

6.96e8 === 696000000
1e-10 === 0.0000000001

1e3 は $ 1×10^3 $、

6.96e8 は $ 6.96×10^8 $、

1e-10 は $ 1×10^{-10} $


文字列


1文字取り出す

const str = "abcdefg";

// 3文字目取り出す
str.substring(2, 1); //> "c"

const str = "abcdefg";

str[2]; //> "c"


オブジェクト


プロパティ名とキーが一致している


before

const obj = {

lorem: lorem,
ipsum: ipsum
}


after

const obj = {

lorem,
ipsum
}


プロパティに関数を代入する ※追記

@yuta0801 さんより追記


before

const obj = {

name : "Alice",
greet: function() {
console.log(`I'm ${this.name}`);
}
}


after

const obj = {

name : "Alice",
greet() {
console.log(`I'm ${this.name}`);
}
}


配列をそれぞれの変数に代入する


before

const first = arr[0]

const second = arr[1]
const third = arr[2]


after

const [first, second, third] = arr



プロパティをそれぞれ変数に代入する


before

const id    = obj.id;

const name = obj.name;
const birth = obj.birth;


after

const {id, name, birth} = obj;


分割代入はいろいろなタイミングで使えるので、絶対に覚えておくべき。