【初心者向け】JavaScriptコーディングテクニック

最近、JavaScriptの体系的な学習に取り組んでいます。
以前の実務では少し触れた程度でしたが、改めて基礎から学び直す中で気づいた点をまとめます。

## 目次

* [1.Array.includesと条件判定](#1arrayincludesと条件判定)
* [2.Setによる重複除去](#2setによる重複除去)
* [3.Mapと辞書型データ構造](#3mapと辞書型データ構造)
* [4.関数型プログラミングによるデータ処理](#4関数型プログラミングによるデータ処理)
* [5.関数の合成（compose）](#5関数の合成compose)
* [6.文字列の反転](#6文字列の反転)
* [7.Array.fromを利用した配列生成](#7arrayfromを利用した配列生成)
* [8.setTimeoutを活用してsetIntervalを代替](#8settimeoutを活用してsetintervalを代替)
* [9.配列の走査時にfor inを避ける](#9配列の走査時にfor-inを避ける)
* [10.分割代入（解構賦値）の活用](#10分割代入解構賦値の活用)

> 随時更新中:fish: ...

## 1.Array.includesと条件判定

通常、条件分岐には || を使います：

``` javascript
function testFruit(fruit) {
  if (fruit == 'apple' || fruit == 'orange') {
    console.log(`I love it`);
  }
}
```

しかし、比較する値が増える場合、より効率的に記述するにはArray.includesを利用します：

``` javascript
function testFruit(fruit) {
  const sweetFruits = ['apple', 'cherry', 'orange', 'banana'];
  if (sweetFruits.includes(fruit)) {
    console.log(`Sweet fruit`);
  }
}
```

## 2.Setによる重複除去

`Set`は配列に似たデータ構造ですが、要素の重複を許しません。

* 配列の重複除去

``` javascript
const arr = [1, 1, 5, 3, 5, 3, 2];
const unique = [...new Set(arr)];
console.log(unique); // [1, 5, 3, 2]
```

* Setを配列へ変換して重複除去関数を作成

``` javascript
function unique(array) {
  return Array.from(new Set(array));
}
unique([1, 1, 2, 4]); 
// 結果: [1, 2, 4]
```

* 文字列の重複を削除

``` javascript
let str = [...new Set('ababc')].join('');
console.log(str); // 'abc'
```

* Setを使った和集合・積集合・差集合

``` javascript
let setA = new Set([1,2,3]);
let setB = new Set([4,3,2]);

// 和集合
let union = new Set([...setA, ...setB]);
console.log(union); // set {1,2,3,4} 

// 積集合
let intersect = new Set([...setA].filter(x=>{
  return setB.has(x);
}));
console.log(intersect); // set {2,3}

// 差集合1
let diff1 = new Set([...setA].filter(x=>{
  return !setB.has(x);
}));
console.log(diff1); // set {1}

// 差集合2
let diff2 = new Set([...setB].filter(x=>{
  return !setA.has(x);
}));
console.log(diff2); // set {4}
```
:::note warn
`Set`には、集合演算を行うための組み込み関数が既に用意されています。
これらの関数を使用することをお勧めします。詳しくは、以下のMDNドキュメントをご参照ください。
:::
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Set

## 3.Mapと辞書型データ構造

ES6で導入されたMapは、キーと値のペアを保持するデータ構造で、キーには任意の型を指定可能です。

* 基本操作

``` javascript
   // 追加
   const resultMap = new Map();
   resultMap.set('0','1111');
   resultMap.set('hoge',['1',2]);

   // 取得
   resultMap.get('hoge');
   // ["1", 2]

   // 削除
   resultMap.delete('0');
   // true

   // JSONに変換
   resultMap.toJSON();
   // [Array(2)]

   // 値の更新
   resultMap.set('hoge', '1111');
   // Map(1) {"hoge" => "1111"}

   // サイズ
   resultMap.size;
   // 1

   // クリア
   resultMap.clear();
```

* Mapの反復

Mapのキーや値を順序通りに反復することが可能です：

``` javascript
const map = new Map([["F", "yes"], ["S", "no"]]);

for (let key of map.keys()) {
  console.log(key);
}
// 出力: F, S

for (let value of map.values()) {
  console.log(value);
}
// 出力: yes, no
```

## 4.関数型プログラミングによるデータ処理

* データを変換・フィルタリングする  
配列のオブジェクトから年齢が16歳以上の人物を抽出し、構造を変更する例です

``` javascript
let foo = [
  { name: "Stark", age: 21 },
  { name: "Jarvis", age: 20 },
  { name: "Pepper", age: 16 }
];

let results = foo
  .filter(person => person.age > 16)
  .map(person => ({
    person,
    friends: []
  }));
```

* 配列の合計を求める

``` javascript
let arr = [1, 2, 3, 5];
let sum = arr.reduce((a, b) => a + b);
// 結果: 11
```

## 5.関数の合成（compose）

関数の合成とは、2つの関数を組み合わせて新しい関数を作る仕組みです。

``` javascript
var oldCompose = function(f,g) {
  return function(x) {
    return f(g(x));
  };
};

/* ES6の書き方 */
const compose = (f, g) => x => f(g(x));

// 使用例
const toUpperCase = x => x.toUpperCase();
const exclaim = x => x + '!';
const shout = compose(exclaim, toUpperCase);

console.log(shout("hello")); 
// 結果: "HELLO!"
```

## 6.文字列の反転

``` javascript
let str = 'hoge';
console.log([...str].reverse().join(''));
// 結果: "egoh"
```

## 7.Array.fromを利用した配列生成

`Array.from`を用いて、簡単に規則的な配列を作成できます。

``` javascript
let hours = Array.from({ length: 24 }, (_, index) => `${index}時`);
console.log(hours);
// 結果: ["0時", "1時", ..., "23時"]
```

## 8.setTimeoutを活用してsetIntervalを代替

`setInterval`はタイミングのズレや「フレーム落ち」が起きやすいため、setTimeoutを用いた方が柔軟です。  
代わりにsetTimeoutを使用

``` javascript
let doSomething = () => {
  // 処理内容
  console.log("処理実行");
  setTimeout(doSomething, 1000);
};

doSomething();
```

## 9.配列の走査時にfor inを避ける

`for in`を使うと配列のプロトタイプチェーンも巡回してしまうため、予期しない動作が発生する可能性があります。

``` javascript
let arr = [1, 2];
Array.prototype.test = function() {};

for (let key in arr) {
  console.log(arr[key]); 
  // 結果: 1, 2, ƒ test() {}
}
```

## 10.分割代入（destructuring assignment）の活用

* 三層以上のネストには注意
あまりにも深い構造の分割代入は可読性を損ないます。

``` javascript
// 悪い例
let { documentElement: { firstElementChild: { nextSibling }} } = window;
```

* 一時変数を減らす記述
分割代入は、値の交換などの場面で便利です

``` javascript
// good
[x, y] = [y, x];

// bad
let temp = x;
x = y;
y = temp;
```