覚えておきたい可読性を上げるJavaScriptの書き方

## else ifを減らす
- `else if`が出現したら、最適化できないかどうか検討します。
- 名前から食べ物の価格を計算する必要がある場合を例にします。
```JavaScript
const getPrice = (name) => {
    if (name === '🍔') {
        return 20;
    } else if (name === '🍟') {
        return 15;
    } else if (name === '🍦') {
        return 5;
    }
}

console.log(getPrice('🍔')); // 20
```
- この書き方では条件判定文が多くなり、次に食べ物を追加したい場合は`else if` を追加する必要があり、オープン・クローズの原則にもある程度違反します。
- Map構造のデータを使用して、すべての食べ物を保存するオブジェクトを作成します。
```JavaScript
const foodMap = {
    '🍔': 20,
    '🍟': 15,
    '🍦': 10,
    '🍩': 10,
    '🍪': 4,
    '🍫': 8,
    '🍬': 1,
    '🍭': 2,
}
const getPrice = (name) => {
    return foodMap[name];
}

console.log(getPrice('🍟')); // 15
```
- 食べ物を追加する際に `getPrice`のロジックを変更する必要が無くなりました。

## 冗長になるループの代わりにパイプライン操作
- こんな食べ物リストがあります
```JavaScript
const foods = [{
    name: '🍔',
    group: 1
}, {
    name: '🍟',
    group: 1
}, {
    name: '🍦',
    group: 2
}, {
    name: '🍩',
    group: 2
}];
```
- groupが1に属する食べ物を見つけたい場合、まず`for`ループを使った方法が考えられます。
- もっとコードを簡潔にわかりやすくするために、`for`ループの代わりに`filter`と`map`を使用するように置き換えます。
- 最初に配列をフィルタリングしてから`map`で取得したい形に再編成します。
```JavaScript
// ❌
const names = [];
for (let i=0;i<foods.length;i++){
    if (foods[i].group === 1){
        names.push(foods[i].name);
    }
}

// ✅
const names = foods.filter(food => food.group === 1)
    .map(food => food.name);
console.log(names); // ['🍔', '🍟']
```


## find関数による冗長なループの置き換え
- `find`は、配列から特定のプロパティ値で見つけたい場合に役立ちます。
```JavaScript
// ❌
const findFood = (foods, name, group) => {
    for (let i=0;i<foods.length;i++) {
        if (foods[i].name === name && foods[i].group === group) {
            return foods[i];
        }
    }
}
const humbugger = findFood(foods, '🍔', 1);

// ✅
const humbugger =  foods.find(food => food.name === '🍔' && food.group === 1);
console.log(humbugger); // {name: '🍔', group: 1}
```

## includes関数によるループの置き換え
- 配列に特定の値が含まれているかどうかを調べたい場合、`includes`を使用するとコードが簡潔になります。
~~~JavaScript
const foods = ['🍔', '🍟', '🍦', '🍩', '🍪', '🍫', '🍬', '🍭', '🍮', '🍯'];
// ❌
let hasCookie = false;
for (let i = 0; i < foods.length; i++) {
    if (foods[i] === '🍪') {
        hasCookie = true;
        break;
    }
}

// ✅
const hasCookie = foods.includes('🍪');
console.log(hasCookie); // true
~~~

## 早期return
- selectKeyが存在しない場合は結果が確定しているため、以降のコードを読み続ける必要はありません。そうしないと必要以上にコードを読むコストが発生してしまいます。
```JavaScript
// ❌
const activeParentKeys = (selectedKey) => {
    let result = [];
    if(selectedKey) {
        if (selectedKey !== 'key1') {
            result = getParentKeys(selectedKey);
        }
    }
    return result;
}

// ✅
const activeParentKeys = (selectedKey) => {
    if (!selectedKey) return [];
    if (selectedKey !== 'key1') {
        return getParentKeys(selectedKey)
    }
    return [];
}
```
## オブジェクト渡し
- 関数に渡すパラメータが少ない場合は気になりませんが数が増えると少々煩雑になります。
- オブジェクト全体を直接渡すことにより、パラメーターのリストが短くなり、コードが読みやすくなります。
- ただし、モジュール強度がスタンプ結合となるため、一概に良いとは言えません。私はこの書き方が好きです。
```JavaScript
const data = {
    icon: '📖',
    content: 'Document'
}
// ❌
const getDocDetail = (icon, content) => {
    console.log(icon);
    console.log(content);
}
getDocDetail(data.icon, data.content);

// ✅
const getDocDetail = (data) => {
    const {icon, content} = data;
    console.log(icon);
    console.log(content);
}
```

## 演算子の使用
- 新しい変数を作成する場合、参照する変数が`null`または未定義であるかどうかを確認する必要がある場合、簡単な方法で記述できます。
```JavaScript
// ❌
if (selectedKey !== null && selectedKey !== undefined) {
    const activeKey = selectedKey;
} else {
    const activeKey = '';
}

// ✅
const activeKey = selectedKey ?? '';

```