JavaScriptの概念たち (後編)

# この記事について

この記事は「[**JavaScriptの概念たち (前編)**](https://qiita.com/tsin1rou/items/90576b6c00b895478610)」の続きです。本来は1つの記事なのですが、あまりにも長くなりすぎたので分割しました。

# 17. Prototype Chain

JavaScriptには2つの特徴があります。1つは「全てがオブジェクト」でもう1つは「prototypeベースの言語だということ」です。

```javascript
const hoge = {
  a: "hogehoge"
};
console.log(hoge instanceof Object);    // -> true

const fuga = [1, 2, 3];
console.log(fuga instanceof Object);    // -> true

const piyo = new Map([[1, 'one'], [2, 'two']]);
console.log(piyo instanceof Object);    // -> true
```

配列とかMapとかも全部、内部的にはオブジェクトなんですね。

さて、実は全てのオブジェクトには`prototype`というプロパティが存在しています。日本語に訳すと「原型」という感じですね。この`prototype`が`class`の継承のような役割を果たします。

`prototype`の役割を明らかにするために少し実験を行ってみます。

```javascript
// Arrayのprototypeにhogeメソッドを定義すると...
Array.prototype.hoge = function(){
  console.log(this);
}

const foo = [1, 2, 3];
// 全てのArrayから呼び出せるようになる
foo.hoge();     // -> [1, 2, 3]
```

`foo`に`hoge()`メソッドを定義していなかったにも関わらず`hoge()`が呼び出せてしまいます。これが`prototype`の力です。

配列`foo`を定義した時に、同時に`foo.__proto__`という内部プロパティに`Array.prototype`への参照がセットされます。そして`foo.hoge()`が呼び出されるとまず`foo`自身のプロパティに`hoge`が存在するかが確認され、なければ次に`foo.__proto__.hoge`が存在するかを確認します。今回は`foo.__proto__.hoge()`が実行されたというわけです。

同じように`Object.prototype.hoge`を定義してみます。

```javascript
Object.prototype.hoge = function(){
  console.log(this);
}

const foo = [1, 2, 3];
foo.hoge();     // -> [1, 2, 3]

const bar = new Map([[1, 'one'], [2, 'two']]);
bar.hoge();     // -> Map(2) {1 => "one", 2 => "two"}
```

今度は`foo.__proto__.hoge`が存在しません。すると次に`foo.__proto__.__proto__.hoge`を確認します。このように、呼び出したメソッドが存在しなければ見つかるまで親のprototypeをさかのぼり続けます。これがprototypeチェーンの仕組みです。

`Array`も`Map`もオブジェクトの子供なのでprototypeチェーンをさかのぼった結果`Object.prototype.hoge`が実行されたというわけです。

もっとも、今は`class`構文があるので`prototype`を直接触るようなコードを書くことはほぼ無いと思います。

----
基本的に全てのオブジェクトが`Object.prototype`へと繋がっているのですが、`Object.create(null)`を使用することで`__proto__`などの内部プロパティなども一切持たない完全に無のオブジェクトを作成することができます。

```javascript
const hoge = {};
const fuga = Object.create(null);

console.log(hoge);
console.log(fuga);
```

上の`hoge`は`__proto__`を持っていますが下の`fuga`は何も持っていないことがわかります。
<img width="158" alt="スクリーンショット 2018-11-29 20.54.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/6b6a3f8c-a09e-29c3-7846-229970df955b.png">

Mapが無かった頃はこの何もプロパティを持たないオブジェクトをMapの代わりに用いていたそうですが、今は本物のMapがある (#24で解説) のであまり出番はなさそうです。

- [[コラム] Object.prototypeを継承しないオブジェクト](https://jsprimer.net/basic/object/#not-inherit-object)

## コラム：ラッパーオブジェクト

JavaScriptは全てがオブジェクトという話の例に配列やMapをあげたのですが、実はプリミティブな文字列などもオブジェクトのように扱うことができます。

```javascript
console.log(true.toString());       // -> "true"
console.log('hoge'.toUpperCase());  // -> "HOGE"
```

これはプリミティブの要素にアクセスしようとすると内部的にラッパーオブジェクトに自動で変換されるためです。
`true.toString()`は実際には`new Boolean(true).toString`のように処理されます。

この辺りの変換は自動でやってくれるので深く考える必要はありません。わざわざ`new Boolean()`などを書く必要はないということだけ覚えておけば良いでしょう。

# 18. Object.create & Object.assign

Object.createは`prototype`オブジェクトの継承を行うために使用されます。`class`構文と同等のことが関数で実行できるというわけですね。ES5時代には無かったことからわかるように、JavaScriptの`class`は見た目が`class`っぽいだけで、実際には`class`を使わなくても同等のことができるのです。
個人的には`class`を使った方が読みやすいと思います。

例えば#14のようにHogeを継承したFugaを書く場合は以下のようになります。

```javascript
function Hoge(){
  this.name = 'NoName';
}
Hoge.prototype.sayHello = function(){
  return `Hello! I am ${this.name}!`;
}

function Fuga(){
  Hoge.call(this);  // class構文ではsuper()を使う
}
Fuga.prototype = Object.create(Hoge.prototype);
Fuga.prototype.constructor = Fuga;

const fuga = new Fuga();
console.log(fuga.sayHello());   // -> "Hello! I am NoName!"
```

Object.assignは複数のオブジェクトを結合してくれる関数です。
prototypeを結合して多重継承(mixin)のように使用したり、第一引数を`{}`にしてオブジェクトをコピーする用途で多用されていました。今はスプレッド演算子を使用します。

```javascript
const obj1 = { hoge: 'hoge' };
const obj2 = obj1   // これだと参照渡しになる
const obj3 = Object.assign({}, obj1);   // 新しいオブジェクトを作成し、それにobj1の内容をコピーする
const obj4 = {...obj1}; // 今はスプレッド演算子を使う

obj1.hoge = 'fuga';

console.log(obj1.hoge); // -> "fuga"
console.log(obj2.hoge); // -> "fuga"
console.log(obj3.hoge); // -> "hoge"
console.log(obj4.hoge); // -> "hoge"
```

# 19. Array.prototypeの便利な関数たち

`Array.prototype`には配列操作のための便利な関数が色々用意されています。#17で述べたように、`prototype`にある関数はどのArrayオブジェクトからでも呼び出せます。

## 配列をスタックやキューのように使う

スタックとはいわゆる<ruby>LIFO<rt>後入れ先出し</rt></ruby>型のデータ格納方式です。この記事の#1で出てきたコールスタックもスタックの一種で、後から入った関数が先に処理されていましたね。

配列をスタックのように使用するには`push()`と`pop()`を使用します。

```javascript
const stack = [];
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack);         // -> [1, 2, 3]

while( stack.length > 0 ){
  console.log(stack.pop()); // -> 3  2  1
}                           // 後ろから出てくる
```

キューは<ruby>FIFO<rt>先入れ先出し</rt></ruby>型のデータ格納方式です。こっちは`push()`と`shift()`を使用します。

```javascript
const queue = [];
queue.push(1);
queue.push(2);
queue.push(3);
console.log(queue);             // -> [1, 2, 3]

while( queue.length > 0 ){
  console.log(queue.shift());   // -> 1  2  3
}                               // 前から出てくる
```

`push()`は配列の後ろに新しい要素を突っ込んでくれる関数でしたが、配列の前に要素を突っ込むための`unshift()`という関数もあります。

## sort

配列をソートしたい場合は`sort()`という関数を使用します。ただし若干動作に癖があって、全ての要素は内部的に`String`に変換され、辞書順でソートされてしまいます。

```javascript
const arr = [1, 10, 5, 30];
arr.sort();             // 引数無しの場合"1", "10", "5", "30"が辞書順になるようにソートされる
console.log(arr);       // -> [1, 10, 30, 5] (元の型がStringに変換される訳では無い)

arr.sort( (a,b) => (a-b) ); // 数字の大小などでソートする場合は自分で比較関数を書く
console.log(arr);       // -> [1, 5, 10, 30]
```

比較関数をうまく使うことでオブジェクトのソートなどを自由に行うことができます。

```javascript
const items = [
  { name: 'watace', value: 100 },
  { name: 'hoge', value: 90 },
  { name: 'fuga', value: 110}
];

// nameの辞書順でソート
items.sort( (a,b) => {
  if(a.name < b.name) return -1; // 負の数字が返ってこればa<bと判定される
  if(a.name > b.name) return 1;  // 正の数字だとa>bと判定される
  return 0; // 0の場合の順序は保証されない
});
console.log(items);     
// -> [{name: "fuga", value: 110}, {name: "hoge", value: 90}, {name: "watace", value: 100}]

// valueの大小でソート
items.sort( ( a, b ) => ( a.value - b.value ) );
console.log(items);
// -> [{name: "hoge", value: 90}, {name: "watace", value: 100}, {name: "fuga", value: 110}]
```

## map

`map()`は配列の各要素を変形して新しい配列を生成する関数です。元の配列は変化させません。

```javascript
const arr = [1, 2, 3];
const newArr = arr.map( x => x * 2 );

console.log(arr);       // -> [1, 2, 3]
console.log(newArr);    // -> [2, 4, 6]
```

個人的にはデータからReactのコンポーネントを作るときに使っています。

```react
const data = [
  { name: 'watace', value: 100 },
  { name: 'hoge', value: 90 },
  { name: 'fuga', value: 110 }
];

const CardList = (props) => (
  <div>
    {data.map( (item, index) => (
      <Card name={item.name} value={item.value} key={index} />
      )
    );}
  </div>
);
```

## reduce

`reduce()`は配列の全ての要素を1回ずつ見ていって最後に1つの値を返す場合の処理を簡単にかける関数です。例えば合計を返したり、最大値を返したりします。

```javascript
const arr = [1, 2, 3];

const sum = arr.reduce( (acc, cur) => ( acc + cur ) );
console.log(sum);   // -> 6

const max = arr.reduce( (acc, cur) => Math.max(acc, cur) );
console.log(max);   // -> 3
```

引数の関数に渡される値は(前回の戻り値, 今回の値, 今のインデックス, 元の配列)です。

他に単語の出現回数を調べたりすることもできます。

```javascript
const arr = [
  '文章が1行ごとに分けられて配列に入っていると考えます。',
  'こうした文章の中で特定の単語や文字の並びの出現回数を調べるには',
  '正規表現とReduceを使うのが簡単です。'
];

const count = arr.reduce(
  (acc, cur) => acc + ( cur.match(/の/g) || [] ).length,
  0
);
console.log(count); // -> 5 ("の"の出現回数)
```

実は`reduce()`は最初の要素の実行をスキップし、2番目の要素からスタートします。1番目の要素はそのまま最初の`acc`に渡されます。

今回はそれでは困るので、2番目の引数に`0`を設定しています。こうすることで、最初の`acc`に`0`が渡され、配列の最初の要素から順番にコールバックを実行してくれるようになります。

## filter

`filter()`は配列の各要素のうち条件にあったものだけを抜き出して新しい配列を生成する関数です。

```javascript
const arr = ['hoge', 'fuga', 'piyo'];

const newArray = arr.filter( elem => /o/.test(elem) );
console.log(newArray);  // -> ["hoge", "piyo"]
```

`/.../`は正規表現オブジェクトを表します。`RegExp.prototype.test()`は引数に正規表現がマッチするかどうかを判定します。マッチすれば`true`、マッチしなければ`false`です。

`/o/.test(elem)`は`elem`に`o`という文字が含まれるかどうかを判定しています。このfilterとか正規表現とかはスクレイピングをするときにかなり役立つ印象です。

# コラム：関数型プログラミング

この後の章でしばらく関数型プログラミングの話が続くので、関数型プログラミングとはどういうものなのかについて簡単に説明します。

正確性に欠けることを承知の上で言ってしまえば、関数型プログラミングは「関数とデータを引き離す」プログラミング手法のことです。

- 関数が関数外部の状態を変化させない
- 関数が引数以外の入力を受け取らない

数学の関数みたいに考えるとわかりやすいかもしれません。
例えば`f(x)=2x+3`みたいな感じである入力`x`に対してどのような出力をするのかを定義します。
似たような感じで`g(x)=-3x`みたいに定義すると、下のように数学的に記述できるんですね。

```javascript
const f = x => 2*x + 3;
const g = x => -3*x;

const x = 3;    // 入力データ

const data = g(f(x));
console.log(data);  // -> -27

// 何回同じ処理をしても入力が同じなので出力は変化しない
console.log(g(f(x)));   // -> -27
console.log(g(f(x)));   // -> -27
```

実は前の章でみてきたArray.prototypeの関数にあった`sort` `map` `reduce` `filter`は関数型プログラミングの考えに基づいている関数です。すなわち、元の関数を変化させず、同じ入力をすれば何度操作を繰り返しても同じ出力が得られます。

関数型プログラミングの概念をもとにコードを組んでいくと、処理の途中でデータが変化することがなくなるのですが、それを「サイドエフェクトがない」だとか「純粋関数」だとか言うわけです。早速見ていきましょう。

# 20. サイドエフェクトと純粋関数

関数は入出力のルートをそれぞれ2つずつ持っています。

```javascript
const hiddenInput = 5;
const obviousInput = 3;
let hiddenOutput;
let obviousOutput;

const func = x => {
  // 隠れた入出力を持つ
  hiddenOutput = x * hiddenInput;
  return x;
};

obviousOutput = func( obviousInput );
```

関数が隠れた出力を持つ場合、その関数には「サイドエフェクト(副作用)がある」と言い、隠れた入力を持つ場合は「参照透過性がない」と言います。

## サイドエフェクト(副作用)

サイドエフェクトとは日本語でいうと「副作用」のことで、関数を実行した際に何らかの状態を変化させてしまう場合に「サイドエフェクトがある」というように使用します。

```javascript:例1：サイドエフェクトを持つ関数
let a = 0;
const inc = () => {
  a += 1;
};
```

```javascript:例2：サイドエフェクトを持たない関数
const inc = a => a + 1;
```

サイドエフェクトがよくわからなくても、基本的に「関数を実行した際に何が起きるのかがその行だけで明白」にできるように気をつけていれば自然とサイドエフェクトが無いコードが書けると思います。

```javascript:例1：サイドエフェクトを持つ場合
let a = 0;
inc();  // 何が起きているのかパッと見では分からない
inc();
console.log(a); // -> 2
```

```javascript:例2：サイドエフェクトを持たない場合
let a = 0;
a = inc(a);
a = inc(a);
console.log(a); // -> 2
```

### コラム：組み込みオブジェクトの独自拡張

上記の`a = inc(a);`はいまいち見た目が微妙という感想を抱く人もいると思います。そもそも`let`って怪しくてあんまり使う気になれないんですよね。

どうせならパイプ記法的に`const b = a.inc().inc();`みたいに書きたいと思いませんか？

そういう場合はサクッと新しいクラスを作っちゃいましょう。

```javascript
class ExNumber extends Number{
  // ちなみに下のようなsuperするだけのconstructorは省略しても問題ありません。
  constructor(args){
    super(args);
  }
  inc(){
    return new ExNumber( this + 1 );
  }
}
const hoge = new ExNumber(1);
console.log(hoge);  // -> 1
const fuga = hoge.inc().inc().inc();
console.log(fuga);  // -> 4
console.log(hoge);  // -> 1
```

## 参照透過性

参照透過性をもつ関数とは隠れた入力を持たない関数のことで、簡単にいってしまえば「同じ引数で実行すれば必ず同じ返り値になる関数」のことです。

## 純粋関数

純粋関数とは、関数のうち「サイドエフェクトが無い」かつ「参照透過性をもつ」もののことをさします。

外部の状態とは完全に独立しているので、コードを解読する際に考えないといけないことが減ります。状態から独立しているので並列処理にも強いです。

```javascript:純粋ではない例
const addPerson = (group, person) => {
  group.push(person);
}
const group = [];
addPerson(group, { name: 'hoge' });
```

```javascript:純粋な例
const addPerson = (group, person) => {
  return [...group, person];
}
const group1 = [];
const group2 = addPerson(group1, { name: 'hoge' });
console.log(group1);    // -> []
console.log(group2);    // -> [{name: "hoge"}]
```

ネストされたオブジェクトは適当に処理してると参照コピーになるので注意しましょう。

# 21. クロージャー

JavaScriptでは、関数が外側のスコープにある変数への参照を保持できるようになっています。この性質のことを「クロージャー」と呼び、これを利用すると関数にあたかも状態を持つかのような挙動をさせることができます。

```javascript
const createCounter = () => {
  let cnt = 0;
  return {
    inc: () => ++cnt
  }
};

const counter = createCounter();

console.log(counter.inc()); // -> 1
console.log(counter.inc()); // -> 2

// 当然ですが、counterはただの関数です。cntにはアクセスできません。
console.log(cnt); // -> ReferenceError
console.log(counter.cnt); // -> undefined
```

JavaScriptでは不要になったメモリをガベージコレクタが自動で解放してくれるのですが、その解放基準は「グローバルオブジェクトから到達できるかどうか」となっています。

上記の例では`global -> counter -> cnt`と参照されているため、cntのメモリが解放されずに内部状態のように働いています。

# 22. 高階関数(HOF)

JavaScriptでは関数もオブジェクトの一つです。これを利用して関数を引数にしたり戻り値を関数にすることができます。JavaScriptを使い慣れている人なら当たり前すぎて今更何言ってるんだとなるかもしれません。

\#19で出てきた`sort()`や`map()`、`filter()`、`reduce()`は全て引数に関数をとるので高階関数だと言えます。また#21のクロージャーなどで関数を返すものも高階関数だと言えるでしょう。

関数型プログラミングを行う場合にこの高階関数が使えるというのは必須条件になってきます。

# 23. 再帰

再帰の例といえば`5!`みたいな階乗ですよね。

```javascript
const factorial = n => n === 1 ? 1 : n * factorial(n-1);
```

突然出てきた`?`と`:`は3項演算子と呼ばれる演算子です。下記の`foo`と`bar`は同じものをif文と3項演算子で書いてみたもの。

```javascript
const foo = condition => {
  if (condition) {
    return hoge;
  } else {
    return fuga;
  }
};
// ↕︎同じ
const bar = condition => condition ? hoge : fuga;
```

フィボナッチ数なんかも再帰で書くことができます。

```javascript
const fibonacci = n => (
  n === 0 ? 0
    : n === 1 ? 1
      : fibonacci(n-1) + fibonacci(n-2)
);

console.log(fibonacci(0));  // -> 0
console.log(fibonacci(1));  // -> 1
console.log(fibonacci(2));  // -> 1
console.log(fibonacci(3));  // -> 2
console.log(fibonacci(4));  // -> 3
```

ただし、`fibonacci(n-1) + fibonacci(n-2)`を見ればわかるようにこの再帰は分岐しているため`n`が増えるたびに計算時間が約1.618倍になってしまいます。このことについては後ほど#28や#29で扱います。

# 24. コレクションとジェネレーター

JavaScriptのコレクションには`Object`と`Array`の他に`Map`、`Set`、`WeakMap`、`WeakSet`があります。

## Object

Objectは使い慣れすぎていて`Map`を使う気がおきませんね。`for of`で回す時なんかは`Object.entries()`を使うことが多いです。

```javascript
const obj = {
  hoge: 'hoge',
  fuga: 10,
  piyo: {
    piyopiyo: true
  }
};

for( const [key, value] of Object.entries(obj) ){
  console.log(`key: ${key}, value: ${value}`);
    // -> "key: hoge, value: hoge"
    // -> "key: fuga, value: 10"
    // -> "key: piyo, value: [object Object]"
  if(key === 'piyo')console.log(value.piyopiyo);    // -> true
}
```

## Array

まあ配列についても今更特にコメントすることはありません。

```javascript
const arr = [ 'hoge', 'fuga', 'piyo' ];

for( const value of arr )console.log(value);
// -> "hoge"
// -> "fuga"
// -> "piyo"
```

ループを回す時にどうしてもインデックスが欲しい場合は`Array.prototype.entries()`を使います。

```javascript
for( const [index, value] of arr.entries() ){
  console.log(`index: ${index}, value: ${value}`);
}
// -> "index: 0, value: hoge"
// -> "index: 1, value: fuga"
// -> "index: 2, value: piyo"
```

## Map

`Object`との違いは大きく3つあります。

- 任意の値がキーになれる
- 大きさを得るのが簡単 (`Map.prototype.size`で瞬殺)
- `for of`が直感的に使える

```javascript
const fuga = {
  toString: () => 'fugaオブジェクト'
};
const map = new Map([
  [4, 'hoge'],  // 数字もキーになれる
  [fuga, 10],   // オブジェクトもキーになれる
  [true, {      // booleanもキーになれる
    piyopiyo: true
  }]
]);

console.log(map.size);  // -> 3
for( const [key, value] of map ){
  console.log(`key: ${key}, value: ${value}`);
}
// -> "key: 4, value: hoge"
// -> "key: fugaオブジェクト, value: 10"
// -> "key: true, value: [object Object]"
```

ちなみに最後の出力が`[object Object]`となっているのはテンプレートにObjectが埋め込まれると自動で`Object.prototype.toString()`が呼び出されるためです。

## WeakMap

`Map`との違いは大きく2点。

- キーは`Object`のみ
- 列挙不可能

何かが弱い感じの`Map`。何が弱いのかというと参照が弱いです。
弱い参照とはガベージコレクションを妨げない参照のことで、つまりキーとなった`Object`はWeakMap以外で使用されなくなった時点でガベージコレクションの対象となるためメモリを解放することができます。

```javascript
const wm = new WeakMap();

const obj1 = {};
let obj2 = {};

wm.set(obj1, 'object1');
wm.set(obj2, undefined);

console.log(wm.has(obj1));  // -> true
console.log(wm.has(obj2));  // -> true

console.log(wm.get(obj1));  // -> "object1"
console.log(wm.get(obj2));  // -> undefined

wm.delete(obj1);    // 通常のMapと同じように消すことも可能

obj2 = {};  // ※下記

console.log(wm.has(obj1));  // -> false
console.log(wm.has(obj2));  // -> false
```

`WeakMap`からオブジェクトへの参照は弱い参照のため、他の場所からの参照がなくなる上記の`※`時点でもともとの`obj2`のメモリを解放することができます。

- [十六章第一回　WeakMapとWeakSet — JavaScript初級者から中級者になろう — uhyohyo.net](https://uhyohyo.net/javascript/16_1.html)

## SetとWeakSet

一意の値を格納するのに使用できます。Setはなんでも格納できますが、WeakSetはオブジェクトしか格納できません。また、WeakSetは列挙できません。

```javascript
const set = new Set(['👻', '🎉', '🎂', '🎄']);

console.log(set.size);      // -> 4

console.log(set.add('🌟')); // -> Set(5) {"👻", "🎉", "🎂", "🎄", "🌟"}
console.log(set.add('👻')); // -> Set(5) {"👻", "🎉", "🎂", "🎄", "🌟"}

for( const value of set ){
  console.log(value);
}
// -> "👻"
// -> "🎉"
// -> "🎂"
// -> "🎄"
// -> "🌟"
```

## ジェネレーター

ジェネレーターは中断できる感じの`function`です。

```javascript
const hoge = function*(){
  yield 1;
  yield 2;
}

const h = hoge();
console.log(h.next());  // -> {value: 1, done: false}
console.log(h.next());  // -> {value: 2, done: false}
console.log(h.next());  // -> {value: undefined, done: true}

// 列挙することも可能
for( const value of hoge() ){
  console.log(value);   // -> 1  2
}

// マクロのように使えなくもない (あまり記述量が減らない気がするが...)
const rep = function*(x){
  for(let i = 0; i<x; i++){
    yield i;
  }
}
for( const i of rep(5) ){
  console.log(i);       // -> 0  1  2  3  4
}
```

# 25. Promise

PromiseはJavaScriptで非同期処理を簡単に書けるようにしてくれる構文です。一部の処理については今は#26の`async` `await`を使うのが一般的ですが、`async` `await`は内部でPromiseを使用している上にPromiseでしかできない処理もあるので完全に置き換わった訳ではありません。

## Callback地獄の時代

Promise登場以前はCallbackを駆使して非同期処理を行なっていました。しかし非同期処理を連続して行いたい場合、CallbackにCallbackを渡してさらにそのCallbackにまた別のCallbackを渡して...という書き方をするしかありませんでした。

```javascript
// 300ms後にcallbackを実行する関数
const doAfter300ms = (callback)=>{
  setTimeout(callback, 300);
}

doAfter300ms(()=>{
  console.log('1st step');
  doAfter300ms(()=>{
    console.log('2nd step');
    doAfter300ms(()=>{
      console.log('3rd step');
      // 際限なくネストが深くなっていく
    });
  });
});
```

## Promise時代

Promiseを使う場合、非同期関数をPromiseで包んで先に(処理が終わるのを待たずに)Promiseオブジェクトだけreturnします。

Promiseの中身は`resolve` `reject`の2つの引数をとる関数にします。`resolve`が実行されるとそのPromiseが解決され、`.then()`に処理が移っていきます。`reject`が呼ばれると`.then()`をスキップして`.catch()`に処理が移ります。

```javascript
// 300ms後にcallbackを実行する関数
const doAfter300ms = (callback)=>{
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      callback();
      resolve();
    }, 300);
  });
};

console.log(doAfter300ms());    // -> [object Promise] {}

doAfter300ms(()=>{
  console.log('1st step');
})
.then(()=>{
  return doAfter300ms(()=>{
    console.log('2nd step');
  });
})
.then(()=>{
  // 途中で同期的な処理を混ぜることも可能
  console.log('hogehoge');
})
.then(()=>{
  return doAfter300ms(()=>{
    console.log('3rd step');
  });
})
.catch(e=>{
  // Promiseチェーンの中で`reject`が呼ばれたらここに飛ぶ
});
```

なお、`resolve()`に値を設定すると次の`.then()`で受け取ることができます。`reject()`なら`.catch()`で受け取れます。

```javascript
const hoge = new Promise(resolve=>{
  setTimeout(()=>{
    resolve(5);
  }, 300);
});
hoge.then(x=>{
  console.log(x);   // -> 5
});
```

# 26. async/await

`async`は関数の前にくっつけるとその関数が`async function`という非同期処理用の関数に変化します。そして`await`は`async`関数内でのみ使用できるキーワードで、Promiseオブジェクトの前に付けると関数を一時停止してその場でPromiseの解決を待ちます。

```javascript
// 300ms後にcallbackを実行する関数(再掲)
const doAfter300ms = (callback)=>{
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      callback();
      resolve();
    }, 300);
  });
};

(async ()=>{
  await doAfter300ms(()=>{
    console.log('1st step');
  });
  await doAfter300ms(()=>{
    console.log('2nd step');
  });
  await doAfter300ms(()=>{
    console.log('3rd step');
  });
})();
```

`await`はPromiseの返り値を受け取ることもできます。

```javascript
const hoge = new Promise(resolve=>{
  setTimeout(()=>{
    resolve(5);
  }, 300);
});

(async ()=>{
  const x = await hoge;
  console.log(x);   // -> 5
})();
```

なお、`async` `await`では`try ~ catch`構文が使用できる他、[await/catch](https://qiita.com/akameco/items/cc73afcdb5ac5d0774bc)という書き方もできるとのこと。

```javascript
// try ~ catch の例
try {
  const x = await fuga();
} catch (err) {
  console.error(err);
}

// await/catch の例
const x = await fuga().catch( err => {
  console.error(err);
};
```

`try ~ catch`だとブロックスコープができて邪魔という場合などにawait/catchの書き方はかなり便利そうです。

# 27. データ構造

データ構造とはデータの集まりをどのような形式で格納するのかというものです。データ構造次第でどのような処理が得意なのかが決まってくるため、特に処理すべきデータが多い場合には目的に沿って適切なデータ構造を選択する必要があります。

## 配列

※JavaScriptの配列の実装はこの配列とは異なる場合があるので注意。
連続したメモリアドレス上にデータを格納する構造。
それぞれのデータへのアクセスがO(1)で行える。
データの挿入・削除はO(n)。データの探索も基本的にはO(n)になる。

## 連想配列

配列は`a[0]`みたいに数字を添字にしてアクセスするんですが、数字以外の型でアクセスできるようにしたものが連想配列です。JavaScriptは全てのオブジェクトがこの連想配列になっています。
JavaScriptでの実装ではそれぞれのデータへのアクセスやキーの追加・削除などがO(1)で行えます。

ただ、最近のJavaScriptエンジンは優秀で、JavaScriptの配列を上の配列にするみたいな最適化をしてくれるらしいんですよね。この辺りはあまり詳しくないので情報求めてます。

## リスト

データと「別のデータへのポインタ」を保持するデータ構造。
配列に比べると任意の位置での挿入・削除がO(1)でできるというのがメリット。ただしランダムアクセス性は低い。
色々種類がありますが、基本的なもの2つだけ紹介します。

**片方向リスト**
後ろしか指さないタイプのリスト。逆に辿ることはできない。
<img width="424" alt="スクリーンショット 2018-11-23 19.56.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/fbb85f8b-58cc-4225-8961-6ac941342ee5.png">

**双方向リスト**
両方指すタイプのやつ。
<img width="630" alt="スクリーンショット 2018-11-23 19.56.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/8f90636b-44bd-afd2-2af5-6f7e172a278a.png">

## グラフ

頂点と枝からなるデータ構造。
<img width="251" alt="スクリーンショット 2018-11-23 20.11.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/693cd30f-de73-b61b-baf2-0a826f047157.png">

## 木

グラフの一つ。閉路を持たず、全ての頂点が連結されているグラフのこと。
<img width="260" alt="スクリーンショット 2018-11-23 20.21.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/6ff060ed-23da-3799-74a2-0e21746d74a0.png">

例えばDOMはツリーとしてメモリ上に展開されています。

# 28. 計算時間

これまでも何回か使いましたが、*O*記法を使って表現します。詳しい説明は教科書に譲りますが、例えば*O*(1)はデータの量がどれだけ増加しても一定時間で処理できることを意味し、*O*(n)はデータ量に比例して処理時間も伸びていくことを示しています。

## *O*(1)

定数時間という名前がついています。上述の通り、データの量がどれだけ増加しても処理時間が変わらないものを指します。

- Objectのプロパティ読み取り・書き込みなど。

## *O*(log n)

対数時間。ソートされた配列を2分探索する場合など、元のデータの大きさに対して割合でデータ量が減っていく場合などはこの*O*(log n)になります。
データ量が10から100になると処理時間が2倍、1万になると4倍と言う感じ。

## *O*(n)

線形時間。データ量に比例して計算量が伸びていきます。
リストの任意の場所にデータを追加する場合など。（頭から辿る必要があるため）
データ量が10から100になると処理時間は10倍になります。

## *O*(n log n)

実際に使っていくアルゴリズムでかなり見かける(気がする)計算量。
ソート系のアルゴリズムの期待計算量はだいたいこれです。例えばクイックソートだとパーティションの分割が*O*(log n)で、その上で再帰的に全部のデータを見るので合わせて*O*(n log n)となります。

## *O*(n^k)

kは定数を表します。名前は多項式時間。配列全体をk重ループで回すとこの計算量に。
ひとまとめにしていますが、実際に使用する上では*O*(n^2)と*O*(n^3)のようにkの値が違うとかなり計算量が異なってきます。

## *O*(k^n)

指数時間。代表例は巡回セールスマン問題など。
よほどデータ量が少なくない限り実用的ではない計算量です。

# 29. アルゴリズム

アルゴリズムは「処理を行うための一連の手続き」みたいなものです。特に処理すべきデータの量が多い場合など、アルゴリズムの組み方で計算量が全然違ってきます。

\#23でフィボナッチ数列を再帰で実装してみました。

```javascript:再掲
const fibonacci = n => (
  n === 0 ? 0
    : n === 1 ? 1
      : fibonacci(n-1) + fibonacci(n-2)
);
```

しかし上記の実装だと計算量に問題があります。
例えば`n=40`だと`fibonacci(39) + fibonacci(38)`が計算されますが、`fibonacci(39)`を展開してみると
`{ fibonacci(38) + fibonacci(37) } + fibonacci(38)`
となり、`fibonacci(38)`が2回計算されてしまっていることがわかります。

そこで、一度計算したfibonacci数を配列に保存し、2回目以降は保存された数字を利用することにします。

```javascript
const arr = [0, 1];
const fibonacci = n => (
  arr[n] !== undefined
    ? arr[n]
    : arr[n] = fibonacci(n-1) + fibonacci(n-2)
      // JavaScriptでの代入式は代入した値を返します
);

console.log(fibonacci(50));  // -> 12586269025
```

元の再帰が*O*(黄金比^n)だったのに対して新しいメモ化再帰は*O*(n)にできました。

ただこのアルゴリズムというのは奥が深い分野で、とてもこの1章だけで書き切れるものではないんですよね。詳しく知りたい人は蟻本がおすすめです。追加の例として蟻本の名前の由来？ にもなっている「蟻」問題を紹介します。

**問題**

> 長さLcmの竿の上をn匹のアリが毎秒1cmのスピードで歩いています。
> 竿は狭くてすれ違えないので、アリ同士が出会うとお互いに反転します。また、竿の端に到達するとアリは竿の下に落ちていきます。
> 各アリの現在の位置が与えられた時、全てのアリが竿から落ちるのにかかる最大の時間と最小の時間をそれぞれ求めなさい。

```
__.___.__._____.__ (竿の上にいるアリのつもり)
```

**制約**

> 1 ≤ L ≤ 1e6 (注：10^6=1,000,000のことです)
> 1 ≤ n ≤ 1e6
> 0 ≤ xi ≤ L

まず、全てのアリがどちらを向いているのかを場合分けしていくと2^n通りになることが分かります。

|n|1|10|20|30|50|
|--:|--:|--:|--:|--:|--:|
|2^n|2|1024|1e6|1e9|1e15|

nと2^nの関係は上記の通りで、とてもn=1e6のような大きなnを現実的な時間で計算することはできません。コンピューターが1秒間に処理できる計算量はおよそ1e7〜1e8くらいです。(これを逆算すると、問題文の制約がn≤1e6なので*O*(n)の解法を見つけろという問題であることが分かります。*O*(n log n)でも通るかも？)

この解法では現実的な時間で計算できないことが分かりました。別の解法を探す必要があります。

まず簡単そうな最小時間の求め方を考えると、全てのアリを近い方の端に落としてしまえば良いことが分かります。アリ同士が出会わないので簡単に求められます。

次に最大時間はどう求めるのかを考えていきます。よく考えてみると、アリ同士が出会った際にお互い逆方向に進み出すのですが、これはアリ同士がそのまますれ違ったと解釈しても問題ないと分かります。

`➡️⬅️`
↓　　　　　　　　　イメージ図(伝われ)
`↩️↪️` ⇔ `⬅️➡️`

するとそれぞれのアリの向きはどうでもよく、端までの距離がもっとも遠いアリを見つければ良いことが分かります。最大値を見つけるにはそれぞれのアリについて一回ずつ調べれば良いので*O*(n)で解けることが分かりました。

これは極端な例ですが、アルゴリズムを活用すると様々な処理の計算量を落とすことができます。知っ得です。もし初めてアルゴリズムを学ぶという場合はいきなり蟻本を読むと挫折すると思うので、[AtCoder Beginner Contest](https://beta.atcoder.jp/)などを解いてみるのがオススメです。

# 30. ポリモーフィズム

ポリモーフィズムは日本語にすると多態性とか多様性とかいう感じの言葉で、要するに様々な型の入力に対して同じ関数を使用できることを指します。同じ関数を利用できると何が嬉しいのかというと、引数の型ではなく処理の目的に沿って関数を使用できるのでより直感的に理解できるという点が挙げられます。

例えば2つの引数(a, b)をとってその2つが実質的に同じかどうかを判断する関数を書きたいとします。
引数の型がNumberかBooleanか、はたまたObjectなのかで内部の処理は結構変わってきますよね。
でも同じ関数で利用できたら分かりやすくないですか？

必然的に「どうやって型の判断をするのか？」が問題になるのですが、JavaScriptでは`Object.prototype.toString.call()`を使うのが簡単です。[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString)に載ってました。

`Object.prototype.toString`に`call()`か`apply()`でオブジェクトを渡してあげると`[object String]`みたいな感じで戻ってきます。

```javascript
const type = val => {
  return Object.prototype.toString.call(val).slice(8, -1);
};

console.log(type({}));          // -> "Object"
console.log(type(1));           // -> "Number"
console.log(type(false));       // -> "Boolean"
console.log(type('hoge'));      // -> "String"
console.log(type(null));        // -> "Null"
console.log(type([]));          // -> "Array"
console.log(type(/a-z/));       // -> "RegExp"
console.log(type(()=>{}));      // -> "Function"
console.log(type(undefined));   // -> "Undefined"
```

これであとは引数を型ごとに`switch`すればそれぞれの型に合わせた実装を行えます。

自作classの名前が欲しい時は`getPrototypeOf().constructor.name`なんかが良いんじゃないかと思いついたのですが、minifyされた時に名前が変わるので意図通りに動かなくなる問題が発生しがちだそうです。azuさんありがとうございます。

```javascript:❌
const type = val => {
  return val === null
    ? 'Null'
    : val === undefined
      ? 'Undefined'
      : Object.getPrototypeOf(val).constructor.name;
};
```

# 31. デザインパターン

デザインパターンとは、再利用やメンテナンスを楽に行うための設計を分類して名前をつけたものです。

[GoF本](https://www.amazon.co.jp/dp/4797311126)で発明された概念だとWikipediaに書いてありました。一部界隈では聖書のように扱われているそうです。ちなみに[英語版(PDF)](https://sophia.javeriana.edu.co/~cbustaca/docencia/DSBP-2018-01/recursos/Erich%20Gamma,%20Richard%20Helm,%20Ralph%20Johnson,%20John%20M.%20Vlissides-Design%20Patterns_%20Elements%20of%20Reusable%20Object-Oriented%20Software%20%20-Addison-Wesley%20Professional%20(1994).pdf)は無料で読めます。

1994年に登場してからもう20年以上経過していることもあって、デザインパターンの良い部分に触れ続けている今のプログラマーにはその良さが今ひとつ伝わらないのかもしれません。

例えば配列でもMapでも、はたまたジェネレーター関数でも`for of`で回せるのは*Iterator Pattern*のおかげですし、*Prototype Pattern*なんかはJavaScriptの言語の根幹であるとも言えます。DOMのEventListenerは*Observer Pattern*そのものですし。

# 32. カリー化と部分適用

## カリー化

カリー化とは全ての関数の引数の数を1つにすることだと言えます。

```javascript
// カリー化されていない
const add = (a, b) => a + b;
console.log(add(1, 2));     // -> 3

// カリー化されている
const cAdd = a => b => a + b;
console.log(cAdd(1)(2));    // -> 3
```

関数を受け取ってカリー化するための関数を自前で実装すると下のようになります。これは元の関数の引数が2個の時用のものです。

```javascript
const curry = fn => (
  function cfn(a, b) {
    switch (arguments.length) {
    case 0:
      return cfn;
    case 1:
      return _b => fn(a, _b);
    default:
      return fn(a, b);
    }
});

const add = (a, b) => a+b;
const cAdd = curry(add);

console.log(cAdd());        // -> function cfn(a, b){...}
console.log(cAdd(1));       // -> _b => add(1, _b)
console.log(cAdd(1)(2));    // -> 3
console.log(cAdd(1, 2));    // -> 3
```

理解のために書いてみましたが、こういうのを自分で実装するのは危ない気がします。実際は[適当なライブラリ](https://www.npmjs.com/search?q=curry)を使うのが簡単で良いと思います。

## 部分適用

さて、関数がカリー化されている場合に使用できるテクニックが「部分適用」です。ほぼ確実にカリー化とセットで登場します。

部分適用とは「元々の関数の引数の一部を固定する」というもので、前節の例でいうと下記の部分が部分適用です。

```javascript
console.log(cAdd(1));       // -> _b => add(1, _b)
```

`add()`の第一引数が`1`に固定されているのが分かります。これを部分適用と言います。

## メリット

関数をカリー化しておくことで多様な関数を簡単に作成できるようになります。

例えば下記のようなデータがあったとします。

```javascript
const data = [
  {
    id: 1,
    name: 'watace'
  },
  {
    id: 2,
    name: 'hoge'
  },
  {
    id: 3,
    name: 'fuga'
  }
];
```

上記のデータから`id`だけを抜き出す関数と`name`だけを抜き出してみます。

```javascript
const ids = data.map( x => x.id );
const names = data.map( x => x.name );
```

カリー化と部分適用を使うと下記のようになります。

```javascript
// さっき作ったカリー化するための関数を使っています
const get = curry(
  (prop, obj) => obj[prop]
);

const ids = data.map(get('id'));
const names = data.map(get('name'));
```

ま、ちょっと僕もいまいちこのテクニックを使いこなせていないので出てくる例も微妙なんですが、より自然言語らしく表現できるし余計な要素 (例えば`x`とか`=>`とか) が入ってこないのが利点ですね。

----
今年のアドベントカレンダーを見ていたらJavaScript2の1日目に「[JavaScript で forEach を使うのは最終手段](https://qiita.com/diescake/items/70d9b0cbd4e3d5cc6fce)」という記事が上がっていて、その犬の例がカリー化と部分適用の説明に良さそうだったので拝借してみます。

例えば`Array.prototype.filter()`を使って犬のリストからタイプがポメラニアンのものだけを抜き出す関数をみてみます。

```javascript
const pomeranians = dogs.filter(dog => dog.type === 'pomeranian');
```

先ほど使った`curry`を使うと下のように書き換えられます。

```javascript
const type = curry(
  (type, obj) => obj.type === type
);

const pomeranians = dogs.filter(type('pomeranian'));

const poodles = dogs.filter(type('poodle'));
const chihuahuas = dogs.filter(type('chihuahua'));
```

同じようなフィルター関数が簡単に作れるのはかなり便利ですね。

# 33. Clean Code

Clean Codeは2008年に出版された[本](https://www.amazon.co.jp/dp/4048930591)のタイトル。いかに綺麗で読みやすいコードを書くのかについて書かれています。

> 実際、コードを読む時間と書く時間の比率は10:1以上になる。
> 新しいコードを書くための努力として、我々は*常に*古いコードを読んでいる。
>> Indeed, the ratio of time spent reading vs. writing is well over 10:1.
>> We are *constantly* reading old code as part of the effort to write new code.

> Robert C. Martin (2008). *Clean Code: A Handbook of Agile Software Craftsmanship*

ちなみに例によって[英語版pdf](https://www.investigatii.md/uploads/resurse/Clean_Code.pdf)は無料で公開されているんですね。

さて、このclean codeの内容は色々な場所でまとめられているのですが、[このリポジトリ](https://github.com/ryanmcdermott/clean-code-javascript)のまとめが分かりやすかったのでその分類に沿ってその一部を簡単に紹介します。

## 変数
### 発音できて意味のある名前を使う

```javascript:❌
const yyyymmdstr = moment().format('YYYY/MM/DD');
```
```javascript:✅
const currentDate = moment().format('YYYY/MM/DD');
```

### 検索しやすい名前を使う

`5`よりも`SERVER_REQUEST_TIMEOUT_SECONDS`の方が検索しやすいですよね。

### 説明的な変数を使う

```javascript:❌
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);
```
```javascript:✅
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);
```

## 関数
### 引数を2個以下にするのが理想

引数が3個以上ある場合は、その関数があまりにも多くのことをしようとしていないか確かめてみる必要があります。

また、データ入力などの場合はObjectを引数に渡すようにすると呼び出しの際の見通しがよくなります。

```javascript:❌
const addUser = (id, name, age, avator) => {
  ...
};
```
```javascript:✅
const addUser = ({id, name, age, avator}) => {
  ...
};

addUser({
  id: 10001,
  name: 'watace',
  age: 23,
  avator: 'https://...',
});
```

### 1つの関数は1つのことだけを処理するべき

テストも書きやすくなります。

```javascript:❌
const emailClients = clients => {
  clients.forEach( client => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()){
      email(client);
    }
  });
};
```
```javascript:✅
const isActiveClient = client => {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
};
const emailActiveClients = clients => {
  clients
    .filter(isActiveClient)
    .forEach(email);
};
```

### 条件判定は切り分けると読みやすい

```javascript:❌
if (fsm.state === 'fetching' && isEmpty(listNode)){
  ...
}
```
```javascript:✅
const shouldShowSpinner = (fsm, listNode) => {
  return fsm.state === 'fetching' && isEmpty(listNode);
};

if (shouldShowSpinner(fsmInstance, listNodeInstance)){
  ...
}
```

## オブジェクトとデータ構造
### メソッドには出来るだけ`this`をreturnさせる

pipe記法的に続けて書くことができるようになります。

```javascript:✅
class Car {
  constructor(make, model, color) {
    this.make = make;
    this.model = model;
    this.color = color;
  }

  setMake(make) {
    this.make = make;
    // NOTE: Returning this for chaining
    return this;
  }

  setModel(model) {
    this.model = model;
    // NOTE: Returning this for chaining
    return this;
  }

  setColor(color) {
    this.color = color;
    // NOTE: Returning this for chaining
    return this;
  }

  save() {
    console.log(this.make, this.model, this.color);
    // NOTE: Returning this for chaining
    return this;
  }
}

const car = new Car('Ford','F-150','red')
  .setColor('pink')
  .save();
```

## エラーハンドリング
### エラーを握り潰さないこと

```javascript:❌
try {
  functionThatMightThrow();
} catch (error) {
  console.log(error);
}
```
```javascript:✅
try {
  functionThatMightThrow();
} catch (error) {
  // 選択肢1 : console.logよりも目立つ
  console.error(error);
  // 選択肢2 : ユーザーに通知
  notifyUserOfError(error);
  // 選択肢3 : サーバーにエラーレポートを送信
  reportErrorToService(error);
  // もちろん全部行っても良い
}
```

## コメント

コメントが必要になるということはそのコードが複雑になりすぎているということらしいです。

### 明白な内容をコメントしない

<blockquote class="twitter-tweet" data-lang="ja"><p lang="fr" dir="ltr">Code comments <a href="https://t.co/TGVxOybTnA">pic.twitter.com/TGVxOybTnA</a></p>&mdash; Jeff Atwood (@codinghorror) <a href="https://twitter.com/codinghorror/status/983148100301742080?ref_src=twsrc%5Etfw">2018年4月9日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

良いコードはコード自体がドキュメントのようなものになってくれます。
コメントを書かずに済むようなコードを書きましょう。

### 古いコードをコメントアウトして残さない

可読性を下げてしまいます。
`git diff [hash]...[hash]`とかを使ってください。

### 日記を書かない

代わりに`git log -- [file]`を見ます。
また、その行が最後に変更されたコミットを特定したい場合は`git blame`を使いましょう。

# 終わりに

書き始めたら意外と時間がかかって焦りました。
間違いや疑問点などありましたらコメントでおしらせください。

# 参考文献

- [継承とプロトタイプチェーン - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain)
- [図で理解するJavaScriptのプロトタイプチェーン - Qiita](https://qiita.com/howdy39/items/35729490b024ca295d6c)
- [Object.create() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
- [Array - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [関数型プログラミング入門 | POSTD](https://postd.cc/an-introduction-to-functional-programming/)
- [「関数型プログラミングって何？」日本語訳 - Okapies' Archive](http://okapies.hateblo.jp/entry/2016/12/15/021550)
- [Master the JavaScript Interview: What is a Pure Function?](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-pure-function-d1c076bec976)
- [参照透過性と副作用についての提言 - Qiita](https://qiita.com/sasanquaneuf/items/3df1001a027e868e9e0e#%E5%8F%82%E7%85%A7%E9%80%8F%E9%81%8E%E6%80%A7%E3%81%A8%E5%89%AF%E4%BD%9C%E7%94%A8%E3%81%AF%E7%95%B0%E3%81%AA%E3%82%8B%E6%A6%82%E5%BF%B5%E3%81%A7%E3%81%82%E3%81%A3%E3%81%A6%E5%88%86%E9%9B%A2%E3%81%99%E3%81%B9%E3%81%8D)
- [Higher-Order Functions in JavaScript — SitePoint](https://www.sitepoint.com/higher-order-functions-javascript/)
- [再帰的なアルゴリズムの実例集 - Qiita](https://qiita.com/HMMNRST/items/18a206d56a3425e7717b)
- [Map - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map)
- [Array vs Set vs Map vs Object — Real-time use cases in Javascript (ES6/ES7)](https://codeburst.io/array-vs-set-vs-map-vs-object-real-time-use-cases-in-javascript-es6-47ee3295329b)
- [ES6 In Depth: Collections - Mozilla Hacks - the Web developer blog](https://hacks.mozilla.org/2015/06/es6-in-depth-collections/)
- [Promise - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [async function - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function)
- [Big-O Algorithm Complexity Cheat Sheet (Know Thy Complexities!) @ericdrowell](http://bigocheatsheet.com/)
- [Data Structures in JavaScript – Silicon Wat – Medium](https://medium.com/siliconwat/data-structures-in-javascript-1b9aed0ea17c)
- [残業したくないあなたに：データ構造とアルゴリズム - Qiita](https://qiita.com/GushiSnow/items/70765a7cae52c0a1b2b8)
- [データ構造 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0)
- [Time complexity - Wikipedia](https://en.wikipedia.org/wiki/Time_complexity)
- [プログラミングコンテストチャレンジブック [第2版]　～問題解決のアルゴリズム活用力とコーディングテクニックを鍛える～ | 秋葉拓哉, 岩田陽一, 北川宜稔 |本 | 通販 | Amazon](https://www.amazon.co.jp/dp/4839941068)
- [JavaScriptの「型」の判定について - Qiita](https://qiita.com/south37/items/c8d20a069fcbfe4fce85)
- [GitHub - ramda/ramda: Practical functional Javascript](https://github.com/ramda/ramda)
- [Ramda.jsを使った関数型プログラミングの実践 - WPJ](https://www.webprofessional.jp/functional-programming-with-ramda/)
- [Why Curry Helps – Hugh FD Jackson](https://hughfdjackson.com/javascript/why-curry-helps/)
- [食べられないほうのカリー化入門 - Qiita](https://qiita.com/KDKTN/items/6a27c0e8efa66b1f7799)
- [CleanCode読書メモ - Qiita](https://qiita.com/opengl-8080/items/c44814564cd216e50656)
- [GitHub - ryanmcdermott/clean-code-javascript: Clean Code concepts adapted for JavaScript](https://github.com/ryanmcdermott/clean-code-javascript)