JavaScriptの概念たち (前編)

この記事は [**JavaScript Advent Calendar 2018**](https://qiita.com/advent-calendar/2018/javascript) 4日目の記事です。

昨日は@sasurai_usagi3さんで「[CoffeeScriptからJavaScriptに移行する](https://qiita.com/sasurai_usagi3/items/1fdb28f0f6d61de369fa)」でした。栄枯盛衰を感じます。「CoffeeScript」でググろうとしたらGoogleさんが「CoffeeScript オワコン」とサジェストしてきて悲しい気持ちになりました。
<img width="258" alt="スクリーンショット 2018-12-03 13.21.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/547cca0c-25fd-bc3e-b7eb-f8592d1fc36a.png">

明日は@todays-mitsuiさんで「Ramda とか？について」です。

# はじめに

今回はGithubの[33個のJavaScriptの概念](https://github.com/leonardomso/33-js-concepts)という記事がかなり良記事だったので、その記事に乗っていたサイトたちを元にそれぞれの章の解説を書いてみました。

これらの概念を知らなくてもJavaScriptを書くことは多分出来ると思いますが、知っておくと何かと便利かと思います。
元サイトたちは参考文献に載せておくのでさらに詳しく知りたい人はそちらを見てください。

もう2018年も終わってしまうというこのタイミングでES5を念頭においたコードを書くということは無いと思うので、例や解説などは全てES2015(ES6)以降を想定して書いておきます。過去の遺産についてはあまり触れません。ｲﾝﾂｧｧﾈｯﾂｫ✝️ｲｸｽ✝️ﾌﾟﾛｰﾗｰ?

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">IE「あ，お久しぶり！…またブラウザの検索？」<br>自「いや，IEからでないと見られないページがあって」<br>IE「そうなんだ！ …ねえ，通常使うブラウザにする？」<br>自「いいよ，今のままで」<br>IE「そう…あと初期設定が済んでないけど，」<br>自「いいよ，また今度で」<br>IE「そっか…」</p>&mdash; So Takamoto (JK) (@tkmtSo) <a href="https://twitter.com/tkmtSo/status/309489294274359296?ref_src=twsrc%5Etfw">2013年3月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なお、文中では#00という表記を00章の意味で用いています。#0だと「0. ES2015以降の書き方についてのおさらい」を指します。

# ライセンス&クレジット

<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="クリエイティブ・コモンズ・ライセンス" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a>
この記事は[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)ライセンスで提供されます。ご利用はご自由にどうぞ。

文責：*わたせ*
Twitter: [@tsin1rou](https://twitter.com/tsin1rou) Qiita: @tsin1rou
誤字脱字の他、根本的な誤り、もっと良い実装や例の提案などがあればコメント欄もしくは上記twitterまでおしらせいただけると幸いです。

---
なんとJavaScriptの知識にかけてはこの人の右に出るものはいないと言われている[**azu**](https://twitter.com/azu_re)さんにチェックしていただくことができました。週ごとにJavaScriptの最新情報を届けてくれる[JSer.info](https://jser.info/)の運営や[JavaScriptの入門書](https://jsprimer.net/)の執筆などをされていらっしゃる方です。本当にありがとうございます。

チェックしていただいた後に書き加えた部分もあるのでミスがあればだいたいその部分です。

# 後編について

- [JavaScriptの概念たち (後編) - Qiita](https://qiita.com/tsin1rou/items/b30885b189a8ec596c72)

あまりにも長くなったので前編と後編に分けました。後編の内容はこんな感じです。

- 17. Prototype Chain
- 18. Object.create & Object.assign
- 19. Array.prototypeの便利な関数たち
- 20. サイドエフェクトと純粋関数
- 21. クロージャー
- 22. 高階関数(HOF)
- 23. 再帰
- 24. コレクションとジェネレーター
- 25. Promise
- 26. async/await
- 27. データ構造
- 28. 計算時間
- 29. アルゴリズム
- 30. ポリモーフィズム
- 31. デザインパターン
- 32. カリー化と部分適用
- 33. Clean Code

# 0. ES2015以降の書き方についてのおさらい

初心者の人でも読めるように簡単にES2015以降のJavaScriptの書き方についてまとめておきます。

なお、コード例中に出てくる`hogehoge` `fugafuga` `piyopiyo`などは「どんな名前でも良いので適当に決めた例としての名前」です。特に意味はありません。海外だと`foo` `bar` `baz`などがよく使用されます。

## 変数の宣言

JavaScriptを学び始めた頃、変数宣言は`var`を使うと覚えた人も多いと思います。ですが、ES2015以降はもっと良い変数宣言ができたので`var`を使うのはあまりおすすめできません。

ES2015以降は`const` `let`を使います。`const`は再代入ができなくなるという特徴があります。

```javascript
const hoge = 'hogehoge';
let fuga = 'fugafuga';

hoge = 'piyo'; // TypeError: Assignment to constant variable
fuga = 'piyo'; // OK
```

また、JavaScriptは上から順番に実行されていくのでまだ出てきていない変数などは使用できません。`var`は謎仕様によってこの原則に逆らうことがありましたが、`var`のことを忘れれば全て解決です。

```javascript
console.log(hoge); // ReferenceError: hoge is not defined

const hoge = 'hogehoge';
```

## 関数の宣言

`function`という言葉も基本的に使いません。（アロー関数と`this`の挙動が異なるのでその場面だけ使います。詳しくは#15を参照）
`const 関数名 = (`<ruby>`引数`<rt>argument</rt></ruby>`)=>{ 処理 }`と書きます。こうすることで関数名が被ってもエラーが出てお知らせしてくれるようになりました。ま、ESLintを使えという話はあるんですけどね。

```javascript
const hoge = (arg) => {
  return arg * 2;
};
```

上のように`return`の行しかないような関数は省略して`(引数)=>(返り値)`と書けます。

```javascript
const hoge = (arg) => (arg * 2);
const hoge = arg => arg * 2; // さらに()を省略することも可能
```

時々謎の記法を見かけるかもしれませんが落ち着いて考えてみます。

```javascript
const hoge = x => y => x + y; // 謎記法の例
const fuga = x => (y => x + y); // 上と同じ
const piyo = fuga(3); // piyo = y => 3 + y;
console.log(piyo(2)); // -> 5
console.log(fuga(3)(2)); // -> 5
```

# 1. コールスタック

JavaScriptでは関数を呼び出すとコールスタックと呼ばれる部分に呼び出された関数が積み上がっていきます。常に一番上の関数が実行されており、関数の実行が終わって値を返すとスタックから取り除かれ、上から2番目に載っていた関数へと戻っていきます。

例えばこんなコードがあったとします。

```javascript
const hoge = x => x+5;
const fuga = x => hoge(x)*2;
console.log(fuga(3));
```

上の行から順番に実行され、`console.log(fuga(3));`の行まで来ました。

```javascript
   const hoge = x => x + 5;
   const fuga = x => hoge(x * 2) * 3;
-> console.log(fuga(3));
```

このように関数を実行する命令があると、JavaScriptの実行エンジンはコールスタックと呼ばれる場所に関数を積み上げていきます。

|コールスタック|
|:--|
||
||
|console.log(fuga(3))|
|main()|

そして常にコールスタックの一番上を実行します。今回は`fuga(3)`という関数を実行する命令が再び登場するのでさらに積み上げます。

|コールスタック|
|:--|
||
|fuga(3)|
|console.log(fuga(3))|
|main()|

`fuga`を実行すると今度は`hoge`が登場しているので積み上げます。

```javascript
   const hoge = x => x + 5;
-> const fuga = x => hoge(x * 2) * 3;
   console.log(fuga(3));
```

|コールスタック|
|:--|
|hoge(6)|
|fuga(3)|
|console.log(fuga(3))|
|main()|

一番上にある`hoge(6)`を実行します。

```javascript
-> const hoge = x => x + 5;
   const fuga = x => hoge(x * 2) * 3;
   console.log(fuga(3));
```

`11`という返り値を得られたので`hoge(6)`をコールスタックから取り除きます。

|コールスタック|
|:--|
||
|fuga(3)|
|console.log(fuga(3))|
|main()|

一番上にある`fuga(3)`の処理に戻ります。`hoge(6)`=`11`ということがわかったので`33`という返り値が求まります。そして`fuga(3)`をコールスタックから取り除き、新たに一番上に現れた`console.log(fuga(3))`を実行してコンソールに`33`という表示が行われます。その後は`main()`にしたがって次の行の処理へと進んでいきます。

このコールスタックはエラーを追跡する時に便利さを実感できると思います。例えばfugafuga関数がhogehoge関数を呼び出し、そこでエラーが起きたとします。

```javascript
const hogehoge = a => { throw new Error('Something Wrong'); };
const fugafuga = a => hogehoge(a);
fugafuga(1);
```

コンソールなどに表示されるエラーにはコールスタックも表示されていると思います。

```javascript
pen.js:4 Uncaught Error: Something Wrong
    at hogehoge (VM191 pen.js:4)
    at fugafuga (VM191 pen.js:7)
    at VM191 pen.js:9
```

`at [関数名] (... [script名]:[何行目か])`という情報が呼び出しに応じて積み上がっています。下の関数が上の関数を呼び出しているという関係です。

大抵の場合は一番上を見ればエラーの原因が特定できます。

# 2. プリミティブ型
基本データ型というのがわかりやすい表現で好きです。
-> [JavaScript プリミティブ型 (基本データ型)](http://www.yunabe.jp/docs/javascript_primitive_types.html)

[JavaScriptに組み込まれている型](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures)は全部で6個あります。

- Boolean
`true`と`false`

- String
`"abcde"`みたいな文字列

- Number
普通の数字。`100`

- `null`
- `undefined`
`null`は積極的に「無い」事を示すものですが`undefined`は「何も定義されていない」状態を表します。
-> [null と undefined の違い](https://qiita.com/shuhei/items/199281e07925d24059d5)

- Symbol
ES2015で導入された新しい型。ユニークなIDが生成出来る。
-> [ECMAScript6にシンボルができた理由](https://qiita.com/naruto/items/312adeb6145eb6221be7)

# 3. 値型、参照型
2のプリミティブ型にあるものは全て値型です。値型というのは「変数をコピーした時に中身もコピーされる」ということです。

```javascript:値型
let x = 10;
let y = 'abc';

const a = x;
const b = y;

x = 5;
y = 'def';

console.log(x, y, a, b); // -> 5 "def" 10 "abc"
```

`x`と`y`を変えても`a`と`b`は変わりません。これは当たり前という感じ。

| 変数 | 値 |
|:----|:---|
|x|5|
|y|"def"|
|a|10|
|b|"abc"|

##参照型

オブジェクトとか配列とかは参照型です。例えば下のような配列を宣言したとします。

```javascript
const a = [0, 1, 2];
```

すると変数`a`にはアドレスがセットされます。

| 変数 | 値 |
|:----|:---|
|a|<#001>|

| アドレス | データ |
|:----|:---|
|#001|[0, 1, 2]|

ここで下のように変数をコピーしてみると...

```javascript
const b = a;
```

参照だけがコピーされます。

| 変数 | 値 |
|:----|:---|
|a|<#001>|
|b|<#001>|

| アドレス | データ |
|:----|:---|
|#001|[0, 1, 2]|

つまり、`a`の中身を変えると`b`の中身まで変わります。なるほどね🤔

```javascript
a.push(99);
console.log(a, b); // -> [0, 1, 2, 99] [0, 1, 2, 99]
```

値渡ししたい場合は[<ruby>`...`<rt>スプレッド演算子</rt></ruby>](https://qiita.com/Nossa/items/e6f503cbb95c8e6967f8)を使って下のように書きます。

```javascript
const a = [0, 1, 2];
const b = [...a];

a.push(99);

console.log(a, b); // -> [0, 1, 2, 99] [0, 1, 2]
```

そもそも`const`なのに中身が書き換えられるなんてと思った人もいるかもしれませんが、`const`は変数それ自体の再代入を禁止しているだけなので中身はどうとでも書き換えることができます。
`const`が禁止するのは以下のような行為です。

```javascript
const a = [0, 1, 2];
a = []; // -> Uncaught TypeError: Assignment to constant variable.
a = a; // -> Uncaught TypeError: Assignment to constant variable.
```

# 4. 型変換

JavaScriptの型変換は2.の型に合わせて

1. Stringへの変換
2. Booleanへの変換
3. Numberへの変換

の3種類が存在します。

## String
Stringへの変換は一番直感的な型変換だと思います。

```javascript
String(123)           // '123'
String(-12.3)         // '-12.3'
String(null)          // 'null'
String(undefined)     // 'undefined'
String(true)          // 'true'
String(false)         // 'false'
```

また暗黙の型変換として`+`の片方がStringの場合はもう一方もStringに変換されます。

```javascript
String(''+0+1)        // '01'
String(0+''+1)        // '01'
String(0+1+'')        // '1' <- 0+1が先に計算される
```

## Boolean
`''` `0` `-0` `NaN` `null` `undefined` `false`のみが`false`に変換されます。他は全部`true`になります。

```javascript
Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false
Boolean({})           // true
Boolean([])           // true
```

<ruby>`||`<rt>or</rt></ruby> <ruby>`&&`<rt>and</rt></ruby> <ruby>`!`<rt>not</rt></ruby>の3つの論理演算子は暗黙のBoolean型変換を行います。

ただし、`||`と`&&`は型変換を内部でのみ行い、返り値は元の値・型がそのまま返ってきます。
この仕様を利用して条件分岐を省略することができます。
-> [JavaScriptの「&&」「||」について盛大に勘違いをしていた件 - Qiita](https://qiita.com/Imamotty/items/bc659569239379dded55)

```javascript
// player.nameが設定されていなければ'NoName'となる
const name = player.name || 'NoName';

// if文で書くとこうなる
let name;
if(player.name){
  name = player.name;
} else {
  name = 'NoName';
}
```

## Number
一番色々あって面倒なのがNumberへの変換です。

```javascript
Number(null)           // 0
Number(undefined)      // NaN
Number(true)           // 1
Number(false)          // 0
Number(" 12 ")         // 12
Number("-12.34")       // -12.34
Number("\n")           // 0
Number(" 12s ")        // NaN
Number(123)            // 123
```

以下の演算子はNumberへの暗黙の型変換を行います。

- 比較演算子 `>` `<` `<=` `>=`
- ビット演算子 `|` `&` `^` `~`
- 算術演算子 `-` `+` `*` `/` `%` (ただし`+`の片方がStringの場合を除く) 
- [単項の`+`演算子](https://qiita.com/tonkotsuboy_com/items/04feedc8f7e19290efca)
- 比較演算子 `==` `!=` (ただし比較対象が両方ともStringの場合を除く)

また、`==`は`null`と`undefined`の型変換を行わないという特別ルールがあります。

```javascript
null == 0               // false
```

# 5. ==と===の違い

結論から言うと可能な限り`===`を使うべきです。
4.でもみた通り、`==`は暗黙の型変換を行うので意図せぬ挙動の原因となります。
`===`は同じ型・同じ値の場合のみ`true`を返すのでより厳密な比較ができます。

```javascript
false == 0              // true
false === 0             // false
0 == ""                 // true
0 === ""                // false
```

`null`と`undefined`は`==`においてそれぞれにのみ一致します。

```javascript
null == undefined       // true
null === undefined      // false
```

`NaN`は自分自身を含めて何とも一致しないというルールがあります。`NaN`であるかどうか確認したい場合は`Number.isNaN()`を使用します。

```javascript
const a = NaN;
console.log(a === a);     // false
console.log(a === NaN);   // false
console.log(Number.isNaN(a));  // true
```

## typeof

どの型なのか調べる場合には`typeof`が便利です。

```javascript
typeof 3                 // "number"
typeof 'abc'             // "string"
typeof {}                // "object"
typeof true              // "boolean"
typeof undefined         // "undefined"
typeof (()=>{})          // "function"
```

```javascript:使用例
if (typeof hogehoge === 'number'){...}

const fugafuga = value => {
  switch (typeof value) {
    case 'string':
      return 'this is string';
    case 'number':
    ...
  }
}
```

とはいえ、この`typeof`はラッパーオブジェクト (`new Number()`とか) を全部`"object"`と判定してしまうなど一部使い勝手に問題があるので、実際は`Object.prototype.toString.call()`を使うことが多いと思います。詳しくは#30で。

- [JavaScriptの型などの判定いろいろ - Qiita](https://qiita.com/amamamaou/items/ef0b797156b324bb4ef3)

# 6. スコープ
`var`はJavaScriptの闇の歴史の中に葬り去られたと信じているので`let`および`const`についてのみ書きます。
**新しくJavaScriptを書くときに`var`を使ってはいけません。**
-> [本当にvarは駄目な子なのか？ - Qiita](https://qiita.com/raccy/items/487e62a253d65cc9fee6)

`var`を無視すればスコープについては非常に簡単で、`{}`で囲まれたブロックスコープが適用されます。`if`でも`for`でも関数でも、`{}`で囲まれてさえいればスコープが発生すると考えればOKです。

```javascript
const hoge = 'hogehoge';
{
  console.log(hoge); // Uncaught ReferenceError: hoge is not defined
  const hoge = 'fugafuga';
  console.log(hoge); // -> "fugafuga"
}
console.log(hoge); // -> "hogehoge"
```

上記のコード3行目でエラーが発生するのに違和感を覚える人も少なくないと思います。通常の上から解釈されていく言語なら`hoge`がそのスコープ内で未定義だった場合、上のスコープのものが自動で使用されるのが自然でしょう。もちろんJavaScriptでも基本的には上のスコープを見にいくのですが、同名の変数が同じスコープで定義されていると代わりにエラーが出ます。

```javascript
const hoge = 'hogehoge';
{
  console.log(hoge); // -> "hogehoge"
}
{
  // JavaScriptでは同じスコープで同名の変数が宣言されているとエラーになる
  console.log(hoge); // ReferenceError
  const hoge = 'fugafuga';
}
```

これは「宣言の巻き上げ」というJavaScriptの仕様で、全ての変数はスコープの一番上で宣言されたのと同じ扱いになります。ただし、明示的に宣言した場合にはエラーが出ません。

```javascript
{
  let hoge;
  console.log(hoge); // -> undefined
  hoge = 'hogehoge';
}
{
  console.log(hoge); // ReferenceError
  let hoge = 'fugafuga';
}
```

# 7. <ruby>文<rt>Statement</rt></ruby>と<ruby>式<rt>Expression</rt></rb>

JavaScriptのソースコードは`Statement`と`Expression`という2つの構文から成り立っています。StatementはJavaScriptにおける文の単位のことで、例えば`if文`だと`if (式) 別の文`という形ですね。Expressionは評価できて値が返る感じのやつです。

Statementをうまく説明できなくて申し訳ないのですが、基本的に「戻り値」がないものがStatementです。以下のような予約語を使用した構文と言えばいいですかね。StatementをExpressionが期待されている部分（関数呼び出しの際の引数など）に使用することはできません。

- `const` `let` 
`(var)`

- `if (else)` `switch`
- `for` `(do) while` `break` `continue`
- `throw` `try catch (finally)`
- 
`(function)`
 functionにはStatementとしてのfunctionとExpressionとしてのfunctionがありますが、StatementとしてのfunctionはJavaScriptの黒歴史として葬り去られたので基本的に使用しません。
-> [関数宣言 vs 関数式 | ES2015+ - Qiita](https://qiita.com/raccy/items/aac3b8e3981564bbd1fa)

StatementとStatementの間には<ruby>`;`<rt>セミコロン</rt></ruby>を使います。ただし、`{ }`で囲まれたブロック文でStatementが終わる際には`;`を付けてはいけません。これが`if(){}`構文とか`while(){}`の後ろに`;`が付いていない理由です。

逆に`if()hoge();`みたいな`{}`を使わない`if`の後ろには通常通り`;`が必要です。

# 8. 即時関数、モジュール、名前空間

即時関数(IIFE, Immediately-Invoked Function Expressions)とは言ってみれば「使い捨ての関数」です。その場で使い捨てるのでグローバル空間を汚染しない他、外部からアクセスできる変数を制御することに使われてきました。

ただし、ES2015以降はブロックスコープの導入やモジュールの登場などにより上記の利点が一切失われ、ただ互換性を保つためだけに残っている書き方です。
**新たにJavaScriptを書く際は即時関数を利用する代わりにモジュールを利用してください。**

## 即時関数

即時関数とは関数を定義してすぐその場で実行する関数のことです。本当は下の例の一番上のように書きたいところなのですが、JavaScriptの構文上これはfunction expressionではなくfunction statementとして解釈されてしまうためエラーとなります。そこで`( )`を使用してfunction expressionであることを示しています。

```javascript
function(){
  ...
}();  // -> Unexpected token

(function(){
  ...
})();  // -> OK

(function(){
  ...
}());  // -> これもOK
```

かつてJavaScriptには`var`という変数宣言がありました。これは`let` `const`とは異なりブロックスコープではなくfunctionスコープだったため、`var`で宣言した変数をローカル化するにはfunctionで囲わなければいけませんでした。

```javascript
(function() {
  var innerScope = 'hoge';
})();

console.log(innerScope); // ReferenceError
```

このとき活躍したのが上記のような即時関数で、`function(){}`構文で生成される関数をその場で実行することで外部からのアクセスを禁止できました。

<ruby>古<rt>いにしえ</rt></ruby>の時代においてはJavaScriptはライブラリを導入する際、htmlに`<script src=...></script>`を依存関係に気をつけながら順番に並べて導入していたため、どこでどんなグローバル変数が使われているのか分かりませんから、謎の競合を起こさないようにするために自分でJavaScriptを書く際は基本的に即時関数を使用していました。

```javascript
var hogehoge = 'hoge';

(function() {
  var hogehoge = 'fuga';
  console.log(hogehoge); // -> "fuga"
})();

console.log(hogehoge); // -> "hoge"
```

しかし今ではモジュールがありますし、また`const`や`let`はブロックスコープが適用されるので即時関数の出番はほぼ無くなったと言えるでしょう。

```javascript
const hogehoge = 'hoge';

{
  const hogehoge = 'fuga';
  console.log(hogehoge); // -> "fuga"
}

console.log(hogehoge); // -> "hoge"
```

## モジュール

**この章の例はあくまでモジュールを紹介するためだけに書きました。多くの場合、これを参考にするのではなく#14で紹介する`class`を使う方が妥当かと思われます。**

モジュールは別ファイルに分けて作成します。

```javascript:hogehoge.js
let cnt = 0;
export const inc = () => ++cnt;
```

別ファイルでexportしたものをimportで呼び出すことができます。

```javascript:main.js
import { inc } from './hogehoge.js';
console.log(inc()); // -> 1
console.log(inc()); // -> 2
```

名前空間を分けたい場合は次のように書きます。

```javascript:main.js
import * as counter from './hogehoge.js';
console.log(counter.inc()); // -> 1
console.log(counter.inc()); // -> 2
```

```javascript:main.js
import { inc as hogehogeIncrement } from './hogehoge.js';
console.log(hogehogeIncrement()); // -> 1
console.log(hogehogeIncrement()); // -> 2
```

上記のような`hogehoge.js`の書き方をすると内部の変数は同じものになっていて、どこから呼び出しても同じ値が返ってきます。


```javascript:hogehoge.js
let cnt = 0;
console.log('hogehoge');
export const inc = () => ++cnt;
```

```javascript:foo.js
import { inc } from 'hogehoge.js';
console.log('foo');
inc();
```

```javascript:bar.js
import { inc } from 'hogehoge.js';
console.log('bar');
inc();
```

```javascript:main.js
import './foo.js';
import './bar.js';
// -> 'hogehoge'
// -> 'foo'
// -> 1
// -> 'bar'
// -> 2
```

インスタンスを切り分けたい場合は次の節に出てくる`class`を利用します。

## export default

モジュールが1つのオブジェクトしか`export`しない場合は`export default`を使うことが多いです。

```javascript:hogehoge.js
class Hogehoge {
  constructor(){
    this.count = 0;
  }
  inc(){
    return ++this.count;
  }
}
export default Hogehoge;
```

```javascript:main.js
import Hoge from './module';

const counter = new Hoge();
console.log(counter.inc()); // -> 1
console.log(counter.inc()); // -> 2
```

上記のようにclassの`export`でよく使うように思います。

`import`とは違い、`require()`には`default`を標準で読み込んでくれるような機能はないので、何らかの事情で`require()`を使って`default`を`import`する場合は`require().default`とする必要があります。

## ブラウザでのモジュール

ブラウザでも`<script src="..." type="module"></script>`のように`type`を指定すればESModulesを[使用できます](https://qiita.com/y_catch/items/9349f4b5180c45f73fa7)。※ただしIEを除く

将来的にはwebpackでバンドルする必要も無くなるのかもしれませんが、現状ではnpmモジュールの多くがESModules形式に対応していないなどの問題があるためまだしばらくwebpackの天下は続くと思います。

あとファイルをダウンロードして`import`文を見つけて別のファイルをダウンロードして...というのは遅いですからね。http/2とか[http/3](https://qiita.com/inductor/items/61b824289ac9b2f11b3e)ならまだしもhttp/1.1だとリクエスト数の制限のせいで複数ファイルのダウンロードが遅いので最悪です。

- [Webpack の考え方について - mizchi's blog](https://mizchi.hatenablog.com/entry/2018/11/26/164523)

# 9. イベントループとメッセージキュー

JavaScriptは基本的にシングルスレッドで動作しているため、本来は全てのコードが同期的に動きます。つまり、1つの処理を行なっている間は他の処理を行うことができません。しかしそれでは不便だということでイベントループとメッセージキューという仕組みがあります。これらの仕組みによって擬似的に非同期処理を実現しています。

ここで重要なのですが、イベントループはJavaScriptエンジンの外部にあるものだということに注意してください。JavaScriptを制御しているのは実はイベントループの方であり、エンジンは渡された関数を実行するだけです。また、擬似的と書いたように実際には同期的に動作しているため、コールスタックに他の処理が入っている場合はイベントループは動きません。

イベントループの細かな設計は環境によって異なりますが、この章ではNode.jsの例を見ていきます。[Node.jsのイベントループのページ](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)では以下のような図で説明されています。

```:イベントループ
   ┌───────────────────────────┐
┌─>│           タイマー          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │      未解決のコールバック      │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
```

JavaScriptエンジンにコールスタックがあるのとは対称に、イベントループにスタックはなく、代わりに複数のキューから成り立っています。

## いつイベントループが動作するのか

JavaScriptを実際に走らせると、まず自分の書いたコードが上から下まで実行されます。この実行が終わったら、つまりコールスタックが空になったらイベントループに入ります。

「入ります」と書きましたが、`node.js`の場合はまずイベントループを動かす必要があるかどうかのチェックが行われます。イベントループで何も行われない場合はループに入らず、プロセスの終了処理を行います。

タイマーがセットされていたり、接続の待ち受けを行なっていたりするなど何らかの処理が残っている場合にはイベントループが動き始めます。

## タイマーフェーズ

イベントループはこのフェーズから始まります。

名前の通り内部にタイマーを保持しており、指定した時間が経過したコールバックを実行します。この説明を読めば分かるように、`setTimeout`とかのタイマー系関数は指定時間経過後にイベントループがタイマーフェーズに戻ってくるまで実行されません。

コールバックというのはまあ要するに関数の事で、関数の実行が終わった際に実行する別の関数の事を特別にそう呼びます。相手に電話して「〜〜のタイミングで〇〇に<ruby>掛け直<rt>call back</rt></ruby>してね」と言うイメージ。

例えば、`A` `B` `C` `D`の4つのタイマーをセットした場合を考えてみます。

```javascript:timer
setTimeout(A, 100);
setTimeout(B, 200);
setTimeout(C, 300);
setTimeout(D, 400);
```

タイマーがセットされると、登録されたコールバックはタイマーフェーズ用のキューに昇順で並べられます。

|A|B|C|D|
|:--|:--|:--|:--|

さて、main.jsの他の処理が終わるまで時間がかかり、タイマーフェーズが始まる際にすでに250ms経過していたとします。すると今回のタイマーフェーズでは`A` `B`が実行され、`C`の時間をチェックしてまだ到達していなければそこでタイマーフェーズが終了します。他にも、「Timerフェーズで使っていい時間」の制限もあるため、あまりにも長い処理を行なった場合は残りのタイマーは（時間がきていたとしても）スキップされ、次のタイマーフェーズまで先送りされます。

## <ruby>未解決の<rt>pending</rt></ruby>コールバック

イベントループの`pending queue`に並んでいるコールバックを実行します。
`pending`という名前の通り、1つのイベントループ内で処理しきるには遅すぎるものが複数のイベントループに渡って実行されます。代表例はファイルi/oやネットワーク接続。

キューが空になるか一定時間経過すると次のフェーズに移行します。

## Idle ＆ Prepareフェイズ

次の`poll`フェイズの準備を行います。
Node内部の処理も行われるらしいけどよく知りません。

## Pollフェイズ

イベントループで一番大事だと思われるフェイズ。
JavaScriptで新しくファイルを読み込もうとしたり、外部からの接続を受け取る際にはそれらのタスクは一度`watch_queue`に入れられます。

このPollフェイズでは`watch_queue`に入っているタスクを順番に処理していきます。`watch_queue`が空になっても一定時間はPollフェイズのまま新しい接続を待ち受けます。

## チェックフェイズ

`setImmediate()`のためのフェイズ。`setImmediate()`で追加されたコールバックたちがこのフェイズで実行されます。

`setImmediate()`は`node`環境にしかない関数なのでブラウザでは使えません。

## closeフェイズ

様々な処理のクリーンアップを行います。ソケットのクローズ処理(`socket.on('close',()=>{})`)もここで行われます。

closeフェイズが終わればもう一度イベントループを回す必要があるかどうかをチェックします。イベントループ内の各キューに何も処理が残っていなければプロセスを終了します。

なお、`Promise.resolve()`や`process.nextTick()`はどのフェイズで呼び出されても次のフェイズに行く前に実行されます。同時の場合は`nextTick`が優先されます。

# 10. ブラウザで使用できるタイマー
## setTimeout, setInterval

`setTimeout`と`setInterval`は共にブラウザで使用できるタイマーです。あまりにも古い関数なので引数の順番がキモい。

`setTimeout(callback, delay)`という感じで使います。`delay`ミリ秒以降にcallbackが実行されます。
`setInterval(callback, interval)`の方は`interval`ミリ秒ごとにcallbackが実行されます。

```javascript:index.js
console.log('startTime:', new Date());

setTimeout(()=>{
  console.log('timeout:', new Date());
}, 1000);
const timeout = setInterval(()=>{
  console.log('interval:', new Date());
}, 1000);

setTimeout(()=>{
  clearInterval(timeout);
}, 5000);
```

```console
$ babel-node index.js
startTime: 2018-11-04T02:54:44.630Z
timeout: 2018-11-04T02:54:45.635Z
interval: 2018-11-04T02:54:45.635Z
interval: 2018-11-04T02:54:46.640Z
interval: 2018-11-04T02:54:47.643Z
interval: 2018-11-04T02:54:48.647Z
✨  Done in 5.68s.
```

callbackに引数を渡したい時は
`setTimeout(callback, delay, 引数1, 引数2, ...)`
とするか、
`setTimeout(()=>{callback(引数1, 引数2, ...)}, delay)`
とします。

イベントループはコールスタックが一度空になってから動き始めるのでエラーのデバッグが若干面倒です。

```javascript:index.js
setTimeout(()=>{
  throw new Error('error');  
}, 1000);
```

どのエラーが発生したのかはわかりますが、コールスタックはタイマーのものとなっています。どこでタイマーに突っ込まれたのかは分かりません。

```console
$ babel-node index.js
/Users/watace/qiita_repos/sandbox/index.js:4
  throw new Error('error');
  ^

Error: error
    at Timeout._onTimeout (/Users/watace/qiita_repos/sandbox/index.js:2:9)
    at ontimeout (timers.js:424:11)
    at tryOnTimeout (timers.js:288:5)
    at listOnTimeout (timers.js:251:5)
    at Timer.processTimers (timers.js:211:10)
error Command failed with exit code 1.
```

## requestAnimationFrame

ブラウザでアニメーションというと「**[CSSだけでハロウィン気分の404ページ作った](https://qiita.com/deren2525/items/c1cbd3f582542ef5b4f7)**」のようにCSSでのアニメーションがメインとなっています。

でもCSSの機能だけでは満足できない！！！
もっとJavaScriptで**卍最強卍**のアニメーションを作りたい！！！！

という場合に用意されているのが`requestAnimationFrame`です。
`requestAnimationFrame(callback)`
とすると次の描画の直前にcallbackが実行されます。つまりこれを再帰させて下のコードの様にすると描画ごとに実行される関数の完成です。

```javascript
const animation = ()=>{
  requestAnimationFrame(animation);
  // ここで描画処理
};
requestAnimationFrame(animation);
```

アニメーションに`setInterval(animation, 1000/60)`を使うのは避けましょう。フレームの更新と実行タイミングが合わない上に、ブラウザの実装によっては別のタブを開いていても実行され続けてしまう場合があります。

# 11. JavaScriptエンジン

世の中にはJavaで動く「[Rhino](https://ja.wikipedia.org/wiki/Rhino)」やSafariなどで使われている「[JavaScriptCore](https://en.wikipedia.org/wiki/WebKit#JavaScriptCore)」、Firefoxの「[SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey)」、Google Chromeの「[V8](https://en.wikipedia.org/wiki/Chrome_V8)」など様々なJavaScriptエンジンが存在しています。

これらのエンジンはJavaScriptのコードを機械語に変換する役割を果たしています。エンジンごとに様々な方法でJavaScriptを機械語に変換しているのですが、ここでは「V8」について詳しくみていきます。

## 抽象構文木(AST)

V8エンジンはまずソースコードの構文解析を行い、抽象構文木を構築します。

```javascript:code
var a;
```

```javascript:AST
{
  "type": "Program",
  "start": 0,
  "end": 6,
  "range": [
    0,
    6
  ],
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 6,
      "range": [
        0,
        6
      ],
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 5,
          "range": [
            4,
            5
          ],
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 5,
            "range": [
              4,
              5
            ],
            "name": "a"
          },
          "init": null
        }
      ],
      "kind": "var"
    }
  ],
  "sourceType": "module"
}
```

## Ignition

V8ではバージョン5.9以降(⇒Chrome 59以降)、「Ignition」というインタプリタが使用されており、このIgnitionはASTを[バイトコード](https://github.com/v8/v8/blob/master/src/interpreter/bytecodes.h)に変換します。

バイトコードとは機械語を若干抽象化したようなものです。例えば下記のような関数があるとします。

```javascript
const f = (a, b, c) => {
  const d = c - 100;
  return a + d * b;
}
```

これをバイトコードにするとこんな感じです。`node`を実行するときに`--print-bytecode`をつけると出力してくれます。

```
LdaSmi #100 // accumulatorに100をコピー
Sub a2      // a2からaccumulatorを引く (c-100)
Star r0     // r0にaccumulatorをコピー (d=50)
Ldar a1     // a1からaccumulatorにコピー
Mul r0      // accumulatorにr0を掛ける (d*b)
Add a0      // accumulatorにa0を足す (a+(d*b))
Return      // accumulatorの値を返します
```

引数はレジスタに入れて渡します。例えば`f(5, 2, 150)`の時のレジスタはこんな感じ。

|レジスタ|値|
|:--:|:--:|
|a0|5|
|a1|2|
|a2|150|
|r0|undefined|
|accumulator|undefined|

## TurboFan

Ignitionによって生成されたバイトコードを機械語に翻訳してくれるのがTurboFanです。
機械語っていうとこんな感じのやつです。

```
movl rbx, [rax+0x1b]
REX.W movq r10,0x100000000
REX.W cmpq r10,rbx
...
```

# 12. ビット演算子

コンピューターは`0`と`1`で成り立っているのですが、その2進数表現で出てくる演算がビット演算です。

JavaScriptにもビット演算子が存在します。何に使うのか分かりませんが。競技プログラミングとか組み込み系とかをJavaScriptでやる人がいれば役立つかもしれません。

## <ruby>&<rt>and</rt></ruby>

ANDというのは2つの入力が共に`1`だったら`1`を出力する演算です。

|入力1|入力2|出力|
|:--|:--|:--|
|0|0|0|
|1|0|0|
|0|1|0|
|1|1|1|

`&`演算子はこのAND演算を2進数のそれぞれの桁に対して行います。
例えば`3&6`を考えてみると、`3`は`0011`であり`6`は`0110`なので

||8|4|2|1|10進数|
|:--|:--|:--|:--|:--|:--|
|入力1|0|0|1|1|3|
|入力2|0|1|1|0|6|
|出力|0|0|1|0|2|

となります。

```javascript
console.log(3 & 6);     // -> 2
console.log(12 & 15);   // -> 12
```

## <ruby>|<rt>or</rt></ruby>

ORは2つの入力のどちらかが`1`だったら`1`を出力する演算です。

ANDというのは2つの入力が共に`1`だったら`1`を出力する演算です。

|入力1|入力2|出力|
|:--|:--|:--|
|0|0|0|
|1|0|1|
|0|1|1|
|1|1|1|

例えば`3|6`はこんな感じです。

||8|4|2|1|10進数|
|:--|:--|:--|:--|:--|:--|
|入力1|0|0|1|1|3|
|入力2|0|1|1|0|6|
|出力|0|1|1|1|7|

```javascript
console.log(3 | 6);     // -> 7
console.log(12 | 15);   // -> 15
```

## <ruby>~<rt>not</rt></ruby>

NOTは入力を反転する演算です。マイクラで言うとレッドストーントーチです。

|入力|出力|
|:--|:--|
|0|1|
|1|0|

||8|4|2|1|10進数|
|:--|:--|:--|:--|:--|:--|
|入力|0|0|1|1|3|
|出力|1|1|0|0|12?|

上のように4bitでの演算であれば`~3`は`12`になるように思えます。しかし実はJavaScriptにおいては一番上のbitは**負の数**を表すという決まりがあります。したがって4bitでの`1100`は`-8+4+0+0`なので答えは`-4`となります。

||8|4|2|1|10進数|
|:--|:--|:--|:--|:--|:--|
|入力|0|0|1|1|3|
|出力|1|1|0|0|**-4**|

```javascript
console.log(~3);    // -> -4
console.log(~12);   // -> -13
```

## <ruby>^<rt>xor</rt></ruby>

XOR演算は2つの入力のうちどちらかが`1`であれば`1`を出力する演算です。両方が`1`の時は`0`になります。

|入力1|入力2|出力|
|:--|:--|:--|
|0|0|0|
|1|0|1|
|0|1|1|
|1|1|0|


例えば`3^6`はこんな感じです。

||8|4|2|1|10進数|
|:--|:--|:--|:--|:--|:--|
|入力1|0|0|1|1|3|
|入力2|0|1|1|0|6|
|出力|0|1|0|1|5|

```javascript
console.log(3 ^ 6);   // -> 5
console.log(12 ^ 15); // -> 3
```

## シフト演算子

シフト演算子`<<` `>>` `>>>`を使えばビットを左右に動かすことができます。

例えば`9`は`1001`なので`9<<2`は`100100`、つまり`36`となります。

```javascript
console.log(9 << 2);  // -> 36
```

`>>`はビットを右にずらすのですが、その際左端のビットがコピーされます。

`0000...00001001`を`>>`で2bit右にずらすと`0000...00000010`となり、
`1111...11110111`を`>>`で2bit右にずらすと`1111...11111101`となります。
符号が維持できるというメリットがあります。

```javascript
console.log(9 >> 2);  // -> 2
console.log(-9 >> 2); // -> -3
```

`>>>`は左端に`0`を追加します。

`1111...11110111`を`>>>`で2bit右にずらすと`0011...11111101`となります。

```javascript
console.log(9 >>> 2); // -> 2
console.log(-9 >>> 2);// -> 1073741821
```

## 使い方

### フラグ管理

Linuxでパーミッション変えようとしたときに`777`とか謎の数字を打ち込むことになるのですが、これはフラグを表しています。

`7`というのは2進数だと`111`となるのですが、この一桁一桁がフラグになっています。Linuxのやつだと左から`r` `w` `x`ですね。
`r--`だと`100`なので`4`、`rwx`だと`111`で`7`となります。

特定のフラグが立っているかどうかを調べるには`&`を使います。

```javascript
const xFlag = 1;
const wFlag = 1 << 1;
const rFlag = 1 << 2;

if(flags & rFlag){  // flagsは7とか4とかの数字
  // rが立っている場合に処理が走る
}
if(flags & (rFlag | wFlag) === (rFlag | wFlag){
  // rとwが両方立っていれば走る
}
```

フラグのセットは`|=`なんかを使います。

```javascript
let flags = 0;
// もちろん let flags = wFlag | rFlag; とかでも良い

flags |= rFlag;
```

### 部分和

競技プログラミングでは比較的bit演算が多用される気がします。そのうち一つだけ例を紹介します。

部分和というのは例えば
> `1` `3` `5`という3つのカードを足してできる数字はどんなものがあるのか

という感じの問題です。答えとしては`1` `3` `4` `5` `6` `8` `9`となるのですが、これを求めるのにbit演算が使われます。

最初に0番地だけが`1`のビット列を用意します。
> `0000 0000 0001`

そこにカード`1`の数字分だけ左ビットシフトを行い、元のビット列と`or`をとります。
> `0000 0000 0011`

次のカード`3`の数字分だけ左ビットシフトを行い、元のビット列と`or`をとります。
> `0000 0001 1011`

同じ操作を繰り返します。次は`5`なので5ビットシフトして...となります。
> `0011 0111 1011`
> `BA98 7654 3210`(番地・参考)

何番地が1なのかを調べればどんな部分和が現われるかを求められます。上のビット列では1番目、3番目、4番目、...、9番目が1になっています。

素朴な解法だとO(2^N)だったのがこの解法だとO(N)にできます。

# 13. DOMとレイアウトツリー

DOMはドキュメント・オブジェクト・モデルの略です。簡単にいうと要素のツリーです。

例えばこんな感じのHTMLがあるとします。

```html
<!DOCTYPE html>
<html>
  <head>
    ...
  </head>
  <body>
    <div>
      ...
    </div>
    <script src="..."></script>
    <script src="..."></script>
  </body>
</html>
```

DOMは下のようになります。

```
DOCUMENT (always the root)
 └─HTML
   ├─HEAD
   │  └─...
   └─BODY
      ├─DIV
      │  └─...
      ├─SCRIPT
      └─SCRIPT
```

ブラウザはhtml文章をパースしてDOMを生成します。画面に描画されているのはDOMなので、これを適当に編集すれば画面の表示も変わります。

JavaScriptからDOMを編集する方法は色々あるのですが、代表的なものだけ紹介します。そもそも今時はReactとかVueとか使いますからね。直接編集するようなことはあまりないと思います。

## 要素を取得する

よく使用されるのは`getElementById()`や`getElementsByClassName()`、`querySelectorAll()`などです。

```javascript
// <... id="hoge">みたいにidが"hoge"の要素を取得
const element1 = document.getElementById('hoge');

// <... class="foo bar baz">みたいにクラスに含まれていればまとめて取得
// 返り値はリストになる。
const element2 = document.getElementsByClassName('foo');

// cssのセレクター形式で要素を取得。返り値はリスト。
const element3 = document.querySelectorAll('#hoge'); // id="hoge"の要素を取得
const element4 = document.querySelectorAll('div.highlighted > p'); // p要素のうち直接の親が'highlighted'クラスを持つものを取得
```

## 要素の編集

これもよく使うものだけ紹介します。

```javascript
const element = document.getElementById('...');

// 要素を作成
const hogehoge = document.createElement('div');

// 要素を追加
element.appendChild(hogehoge);

// 要素を削除
element.removeChild(hogehoge);
// 子要素を全削除
while(element.firstChild){
  element.removeChild(element.firstChild);
}

// クラスを取得
const classList = element.classList;
if(classList.contains('fugafuga'){
  // 要素にfugafugaクラスが設定されていれば走る
}

// クラスを追加・削除・切り替え
classList.add('fugafuga');
classList.remove('fugafuga');
classList.toggle('fugafuga'); // 地味にこいつが便利で重宝する
```

## イベント関連

`addEventListener()`と`removeEventListener()`を使います。

```javascript
element.addEventListener('click', (event)=>{
  // preventDefault()を呼ぶと通常の動作が行われなくなる。
  // 例えばaタグをクリックしても移動しなくなったり。
  event.preventDefault();
  console.log('要素がクリックされました');
});

// removeの方は両方の引数を同じにする必要がある
const clickHandler = (event)=>{...};
element.addEventListener('click', clickHandler);
element.removeEventListener('click', clickHandler);
```

`click`以外にどんなイベントがあるかは[Event reference | MDN](https://developer.mozilla.org/en-US/docs/Web/Events)で確認できます。

# 14. ClassとFactory

## Class

ES2015以降は他の言語と同じようにClassを書くことができます。引数がなかった場合の初期値を決めるのには色々流派があるのですが僕は下のようにオブジェクトを利用する方法が好きです。事実上の名前付き引数ですね。ただしデフォルト値を設定する時、方法2の`||`を使う方法は`''`とか`false` `null` `0`とかの代入に失敗するのでその点だけは注意してください。

```javascript
class Hoge {
  // 引数を一つのオブジェクトにするという約束にして、argsで纏めて受け取る
  constructor(args){
    // 初期化処理

    /* 方法1
    this.state = Object.assign({
      name: 'NoName',
      age: 0
    }, args);
    */

    // 方法2
    const { name, age } = args || {};
    this.name = name || 'NoName';
    this.age = age || 0;
  }
  sayHello(){
    return `Hello! I am ${this.name}.`;
  }
  selfIntro(){
    return `${this.sayHello()} And I'm ${this.age} years old.`
  }
}

const hoge = new Hoge();
const fuga = new Hoge({name:'watace', age:23});

console.log(hoge.selfIntro()); // -> "Hello! I am NoName. And I'm 0 years old."
console.log(fuga.selfIntro()); // -> "Hello! I am watace. And I'm 23 years old."
```

`extends`を使うと継承もできます。継承というのは簡単にいうと親のコピー+αを作成するということです。

```javascript
class Piyo extends Hoge {
  constructor(args){
    // super()を使うと親のconstructorを呼び出せます
    super(args);

    const { nakigoe } = args || {};
    this.nakigoe = nakigoe || 'piyo';
    this.capital = this.nakigoe.charAt(0).toUpperCase()
      + this.nakigoe.slice(1); // 先頭を大文字にしてます
  }
  sayHello(){
    return `${this.capital}! ${this.name} ${this.nakigoe}!`
  }
}

const piyo = new Piyo({name:'watace'});
console.log(piyo.selfIntro()); // -> "Piyo! watace piyo! And I'm 0 years old."
```

ただしこのクラス構文はそのメンバーをEventListenerにセットするときに若干問題がおきます。

```javascript
class Foo {
  constructor(args){
    const { name } = args || {};
    this.name = name || 'NoName';
  }
  say(){
    return `${this.name} here!`;
  }
  onClick(event){
    console.log(this.say());  // 上のsay()を呼び出したいが...
  }
}

const foo = new Foo({name:'pizza'});
const elem = document.getElementById('hoge');
elem.addEventListener('click', foo.onClick);
// クリックすると TypeError: this.say is not a function になる
// ↑この時のthisにはelemが入っているため
```

というのもイベントリスナーのハンドラーは呼び出されるときに呼び出し元の要素が`this`になってしまうからです。

これは`this`の問題なので解決方法は色々あります。が、今回はReact界隈で一番よく使用される「constructorで`bind()`する」方法を紹介します。

```javascript
class Foo {
  constructor(args){
    ...
    // bind(this)を行うことで、呼び出された際のthisを今のthisのままにできる
    this.onClick = this.onClick.bind(this);
  }
  ...
}
...
// クリックすると目的通り"pizza here!"となる
```

ちなみにprivateなプロパティを持ちたい場合は`Symbol`を使うと良いようです。
（個人的な感想ですが、publicなプロパティでも直接編集するのはやめた方が良いと思います。インスタンスのプロパティを直接編集しているコードはどこで何をされたか分からず見た瞬間警戒心がMaxになるので。）

```javascript:Symbolって何？
// 自分自身としか一致しないユニークなオブジェクトを生成する
const symbolA = Symbol();
console.log(symbolA === symbolA); // -> true
console.log(symbolA === Symbol()); // -> false
```

```javascript
const __name__ = Symbol();

class Bar {
  constructor(args){
    const { name } = args || {};
    this[__name__] = name || 'NoName';  // Symbolの場合
    this.name = name || 'NoName';       // 通常のプロパティ
  }
  sayHello(){
    return `Hi, I'm ${this[__name__]}`;
  }
}
const bar = new Bar({name:'watace'});
bar.name = 'hoge';          // 直接プロパティを編集できる
console.log(bar.name);      // -> "hoge"😢
console.log(bar.sayHello());// -> "Hi, I'm watace"👍

// __name__を知っていれば直接アクセスできる
console.log(bar[__name__]); // -> "watace"

// これを避けるにはモジュール化してclassだけをexportすればOK
// インポート先では__name__は分からない
export default Bar;
```

ただしシンボルは`Reflect.ownKeys()`で列挙されてしまうとのこと。
アクセスを完全に防ぐには`WeakMap`を使うのが良いらしいです。(azuさんに教えていただきました。ありがとうございます)

```javascript:✅
const __name__ = new WeakMap();
class Baz {
  constructor(args){
    const { name } = args || {};
    __name__.set(this, name);
  }
  sayHello(){
    return `Hi, I'm ${__name__.get(this)}`;
  }
}
const baz = new Baz({name: 'watace'});
console.log(baz.sayHello());    // "Hi, I'm watace"
```


### コラム： JSDocについて

上記のような`args`オブジェクトで全部の引数をまとめて受け取っちゃうような場合、どんなプロパティを設定すればいいのか分からなくなると思います。そこで活躍するのがドキュメントです。

```javascript
class Hoge {
  /**
   * ここにclassの説明
   * @param {Object} args ここにargsの説明
   * @param {string} args.name what's your name?
   * @param {number} args.age how old are you?
   */
  constructor(args){
    ...
```

上記の形式で`constructor`の前に書きます。するとエディタが下のような情報を出してくれます。
<img width="260" alt="スクリーンショット 2018-11-11 19.09.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/15df68ef-d0bc-104f-449d-4d7ba335bd1e.png">

補完も動作します。
<img width="458" alt="スクリーンショット 2018-11-11 19.09.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/d544e820-836c-88b5-03c0-6bdf1716f080.png">

また、下のようにメソッドの前に書けば...

```javascript
  /**
   * 挨拶します。
   * @returns {String} hello sentence
   */
  sayHello(){
    return `Hello! I am ${this.name}.`;
  }
```

エディタが情報を出してくれます。
<img width="296" alt="スクリーンショット 2018-11-11 19.12.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/278434/ef2ee2bd-8d6b-653d-7155-66f8ec6fad24.png">

JSDocで良いJavaScript生活を送りましょう😎

- [Use JSDoc: Index](http://usejsdoc.org/index.html)

## Factory

Factoryという大層な名前がついていますが、ざっくり言うとオブジェクト版テンプレートのことです。複雑な引数を持ったクラスを簡単に作成するために噛ませたりします。

```javascript
// 年齢を半分に詐称するfactory関数
const factory = (name, age) => {
  return new Hoge({name, age: age / 2});
}
```

決まった形式のオブジェクトを簡単に作れるようにするためにも使います。

```javascript
const createIssue = (title, description)=>{
  return {
    title,
    description,
    tag: ['new'],
    date: new Date(),
    status: 'open'
  }
}
```

----
Factoryって全然馴染みがありませんでしたが、よく考えればReduxのActionの生成はこの形式ですね。

```javascript
const receiveData = data => (
  {
    type: 'RECEIVE_DATA',
    data
  }
);
```

# 15. thisとcallとapplyとbind

## this

`function`と`()=>{}`で何が`this`になるかが異なります。

### functionにおいてのthis

`this`は呼び出し方に応じて変化します。呼び出されるまで何が`this`になるか分かりません。

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

hoge();         // -> global

const obj = {
  hoge
};
obj.hoge();     // -> obj

const obj2 = {
  fuga: function(){
    hoge();
  }
};
obj2.fuga();    // -> global???!!!?!?!!?!??!!
```

### <ruby>アロー関数<rt>()=>{}</rt></ruby>においてのthis

コードを見れば何が`this`になるかが分かります。これを「レキシカルな`this`」と言います。
分かりやすいしミスも起きにくいので基本的にアロー関数を使用するようにしましょう。

アロー関数はどこからどうやって呼び出しても`this`は常に同じものをさします。後述の`apply` `call` `bind`を使ってもこの制限を突破してしまうことはありません。

```javascript
const hoge = () => {
  //この段階でthisがglobalなのでどこで呼び出してもglobalになる
  console.log(this);
};

hoge();         // -> global

const obj = {
  hoge
};
obj.hoge();     // -> global

const obj2 = {
  fuga: function(){
    hoge();
  }
};
obj2.fuga();    // -> global
```

## callとapplyとbind

全部「何を`this`にするか」を決めるための関数です。

### callとapply

`call`も`apply`も呼び出す際に何が`this`になるのかを明示的に決定するための関数です。
共に第一引数に`this`にしたいものを入れます。`call`は第二引数以降に直接引数にしたいものを入れていきますが、`apply`は引数をまとめて配列にしたものを第二引数にするという違いがあります。

ただし共にアロー関数の`this`を変えることはできません。

```javascript
const hoge = (arg) => {
  console.log(arg);
  console.log(this);
};
function fuga(arg){
  console.log(arg);
  console.log(this);
}

const obj = {};
const args = ['arg1', 'arg2'];
hoge.call(obj, args);
// -> ["arg1", "arg2"]
// -> global

fuga.call(obj, args);
// -> ["arg1", "arg2"]
// -> Object {}

hoge.apply(obj, args);
// -> "arg1"  (配列が展開されて渡される)
// -> global

fuga.apply(obj, args);
// -> "arg1"
// -> Object {}
```

### bind

`bind`も同じように何を`this`にするかを決められます。こちらは一度決めれば永続的に効果を発揮しますが、アロー関数には使えません。

```javascript
const hoge = () => {
  console.log(this);
};
function fuga(){
  console.log(this);
}

const obj = {};

// bindは新しい関数を返す
const hoge2 = hoge.bind(obj);
const fuga2 = fuga.bind(obj);

hoge();     // -> global (元の関数を変化させない)
fuga();     // -> global
hoge2();    // -> global (アロー関数には効かない)
fuga2();    // -> Object {}
```

# 16. newとインスタンスについて

`new`というのは`Class`の章に出てきた`const hoge = new Hoge()`みたいな奴のことです。この`new`は何を指示しているのでしょうか？

結論から言うと`new`はインスタンスを作成するのに使用します。

```javascript
class Hoge {
  constructor(args){
    console.log(this);
    const { name } = args || {};
    this.name = name || 'NoName';
  }
}
const Fuga1 = (args) => {
  console.log(this);
  const { name } = args || {};
  this.name = name || 'NoName';
}
function Fuga2(args) {
  console.log(this);
  const { name } = args || {};
  this.name = name || 'NoName';
}
                                // thisの中身は？
const hoge1 = Hoge();           // -> TypeError: Class constructor Hoge cannot be invoked without 'new'
const hoge2 = new Hoge();       // -> Object { name:"NoName" }
const fuga1_1 = Fuga1();        // -> global
const fuga1_2 = new Fuga1();    // -> TypeError: Fuga1 is not a constructor
const fuga2_1 = Fuga2();        // -> global
const fuga2_2 = new Fuga2();    // -> Object { name:"NoName" }
```

上の実験から、`new`があれば`constructor`の呼び出し時に新たにオブジェクトが生成されて渡され、`constructor`内の`this`がその新しいオブジェクトを指すようになることが分かります。
`class`や<ruby>`()=>{}`<rt>アロー関数</rt></ruby>がそれぞれどちらかしか行えないのに対して`function`は両方行えてしまいます。`new`をつけると`function`をコンストラクタとして新しいオブジェクトを生成します。

個人的には`new`は`class`と常にセットで使用し、それ以外の場合は使用しないという取り決めが好きです。

## instanceof

インスタンスがどんなクラスを継承してきたのかを確かめるには`instanceof`を使用します。たくさん継承を重ねていても先祖のどこかに存在すれば`true`になります。

```javascript
class Hoge {
  constructor(args){
    ...
  }
}
class Fuga extends Hoge {
  constructor(args){
    super(args);
    ...
  }
}
const hoge = new Hoge();
const fuga = new Fuga();
console.log(hoge instanceof Hoge);  // -> true
console.log(hoge instanceof Fuga);  // -> false
console.log(fuga instanceof Hoge);  // -> true
console.log(fuga instanceof Fuga);  // -> true
```

# 後編へ続く

-> **[JavaScriptの概念たち (後編)](https://qiita.com/tsin1rou/items/b30885b189a8ec596c72)**

# 参考文献(前編)

- [33 Fundamentals Every JavaScript Developer Should Know](https://medium.com/@stephenthecurt/33-fundamentals-every-javascript-developer-should-know-13dd720a90d1)
- [GitHub - leonardomso/33-js-concepts: 📜 33 concepts every JavaScript developer should know.](https://github.com/leonardomso/33-js-concepts#readme)
- [この書籍について · JavaScriptの入門書 #jsprimer](https://jsprimer.net/)
- [JavaScript初級者から中級者になろう — uhyohyo.net](https://uhyohyo.net/javascript/)
- [GitHub - getify/You-Dont-Know-JS: A book series on JavaScript. @YDKJS on twitter.](https://github.com/getify/You-Dont-Know-JS)
- [ES2015(ES6) 入門 - Qiita](https://qiita.com/soarflat/items/b251caf9cb59b72beb9b)
- [イマドキのJavaScriptの書き方2018 - Qiita](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
- [Understanding Javascript Function Executions — Call Stack, Event Loop , Tasks & more](https://medium.com/@gaurav.pandvia/understanding-javascript-function-executions-tasks-event-loop-call-stack-more-part-1-5683dea1f5ec)
- [Primitive Types | Flow](https://flow.org/en/docs/types/primitives/)
- [Explaining Value vs. Reference in Javascript – codeburst](https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0)
- [【Javascript】値渡しと参照渡しについてあらためてまとめてみる - Qiita](https://qiita.com/migi/items/3417c2de685c368faab1)
- [JavaScript type coercion explained – freeCodeCamp.org](https://medium.freecodecamp.org/js-type-coercion-explained-27ba3d9a2839)
- [What you need to know about Javascript's Implicit Coercion - DEV Community 👩‍💻👨‍💻](https://dev.to/promhize/what-you-need-to-know-about-javascripts-implicit-coercion-e23)
- [JavaScript — Double Equals vs. Triple Equals – codeburst](https://codeburst.io/javascript-double-equals-vs-triple-equals-61d4ce5a121a)
- [The old "var"](https://javascript.info/var)
- [JavaScript初級者のためのコーディングガイド - Qiita](https://qiita.com/raccy/items/bf590d3c10c3f1a2846b#_reference-910e146d28f2c4d8f5f5)
- [本当にvarは駄目な子なのか？ - Qiita](https://qiita.com/raccy/items/487e62a253d65cc9fee6)
- [文と式 · JavaScriptの入門書 #jsprimer](https://jsprimer.net/basic/statement-expression/)
- [JavaScript Statements Reference](https://www.w3schools.com/jsref/jsref_statements.asp)
- [JavaScriptの { } を理解する - Qiita](https://qiita.com/uhyo/items/39750a5359629b3fee05#return-completion%E3%82%92%E8%BF%94%E3%81%99%E5%BC%8F)
- [{x: 1} は何と見なされるか —— JavaScriptコンソールによる違い - Qiita](https://qiita.com/8x9/items/8e728e955aaad1d526ae#_reference-47db2a79c722dc2e5ac5)
- [When (and why) you should use ES6 arrow functions — and when you shouldn’t](https://medium.freecodecamp.org/when-and-why-you-should-use-es6-arrow-functions-and-when-you-shouldnt-3d851d7f0b26)
- [関数宣言 vs 関数式 | ES2015+ - Qiita](https://qiita.com/raccy/items/aac3b8e3981564bbd1fa)
- [Do ES6 Modules make the case of IIFEs obsolete? - Hashnode](https://hashnode.com/post/do-es6-modules-make-the-case-of-iifes-obsolete-civ96wet80scqgc538un20es0)
- [関数式 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/function)
- [Essential JavaScript: Mastering Immediately-invoked Function Expressions](https://medium.com/@vvkchandra/essential-javascript-mastering-immediately-invoked-function-expressions-67791338ddc6)
- [ES6のexportについて - Qiita](https://qiita.com/senou/items/a2f7a0f717d8aadabbf7)
- [JavaScriptのexport defaultアンチパターンについて、検証してみた - Qiita](https://qiita.com/genshun9/items/4a00aa6c709b9f024821)
- [export defaultは import { default }で受け取れる - Qiita](https://qiita.com/ohgiwk/items/eac9226ebdffe68b0b88)
- [Node.js event loop workflow & lifecycle in low level | Void Canvas](http://voidcanvas.com/nodejs-event-loop/)
- [Node.jsでのイベントループの仕組みとタイマーについて - 技術探し](https://blog.hiroppy.me/entry/nodejs-event-loop)
- [JavaScript Event Loop Explained – Frontend Weekly – Medium](https://medium.com/front-end-hacking/javascript-event-loop-explained-4cd26af121d4)
- [The Node.js Event Loop, Timers, and process.nextTick() | Node.js](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)
- [Concurrency model and Event Loop - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)
- [Node.jsのイベントループを理解する | POSTD](https://postd.cc/understanding-the-nodejs-event-loop/)
- [Philip Roberts: What the heck is the event loop anyway? | JSConf EU - YouTube](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
- [What is the JS Event Loop and Call Stack? · GitHub](https://gist.github.com/jesstelford/9a35d20a2aa044df8bf241e00d7bc2d0)
- [The JavaScript Event Loop](https://flaviocopes.com/javascript-event-loop/)
- [Timers | Node.js v11.1.0 Documentation](https://nodejs.org/api/timers.html)
- [Canvas と requestAnimationFrame でアニメーション - Qiita](https://qiita.com/hoo-chan/items/398cfc8514c0f1cd984d)
- [Abstract Syntax Tree · Understanding V8 for Javascript Developers](https://www.understandingv8.com/en/ast.html)
- [Understanding V8’s Bytecode – DailyJS – Medium](https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775)
- [JavaScriptでASTを使ってコードをインジェクションしてみる - Qiita](https://qiita.com/erukiti/items/e01b1b2f904f4fb2000e)
- [JavaScript AST Walker](http://azu.github.io/slide/tkbjs/js-ast-walker.html#0)
- [v8 "Launching ignition and Turbofan" 和訳 - kakts-log](http://kakts-tec.hatenablog.com/entry/2017/05/17/004531)
- [Node8.3.0でデフォルトになるTF/Iに関わるベンチマークについて - 技術探し](https://blog.hiroppy.me/entry/2017/08/03/095304)
- [Ignition: An Interpreter for V8 [BlinkOn] - Google スライド](https://docs.google.com/presentation/d/1OqjVqRhtwlKeKfvMdX6HaCIu9wpZsrzqpIVIwQSuiXQ/edit#slide=id.g1357e6d1a4_0_58)
- [Franziska Hinkelmann: JavaScript engines - how do they even? | JSConf EU 2017 - YouTube](https://www.youtube.com/watch?v=p-iiEDtpy6I)
- [ビット演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators)
- [JavaScript Bitwise Operators - w3resource](https://www.w3resource.com/javascript/operators/bitwise-operator.php)
- [Programming with JS: Bitwise Operations – Hacker Noon](https://hackernoon.com/programming-with-js-bitwise-operations-393eb0745dc4)
- [Using JavaScript’s Bitwise Operators in Real Life – codeburst](https://codeburst.io/using-javascript-bitwise-operators-in-real-life-f551a731ff5)
- [ビット演算入門 - Qiita](https://qiita.com/Ingward/items/43acda931c8a62c70d2f)
- [実際のところ「ブラウザを立ち上げてページが表示されるまで」には何が起きるのか - Qiita](https://qiita.com/tsin1rou/items/d4c781a2f25e2b92fa5e)
- [Document - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Document)
- [Element - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Element)
- [ライブラリを使わない素のJavaScriptでDOM操作 - Qiita](https://qiita.com/kouh/items/dfc14d25ccb4e50afe89)
- [Better JavaScript with ES6, Pt. II: A Deep Dive into Classes ― Scotch](https://scotch.io/tutorials/better-javascript-with-es6-pt-ii-a-deep-dive-into-classes)
- [【JSでデザインパターン】ファクトリ編 - Qiita](https://qiita.com/kenju/items/64eaf94803f205dae98c)
- [JavaScriptオブジェクトの作成パターン ES6時代のベストプラクティス - WPJ](https://www.webprofessional.jp/javascript-object-creation-patterns-best-practises/)
- [ES2015 の Class で private なインスタンス変数 - Qiita](https://qiita.com/hkusu/items/e9bbf2e6281980050d3d)
- [JavaScript の this を理解する多分一番分かりやすい説明 - Qiita](https://qiita.com/takkyun/items/c6e2f2cf25327299cf03)
- [JavaScriptの「this」は「4種類」？？ - Qiita](https://qiita.com/takeharu/items/9935ce476a17d6258e27)
- [アロー関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)
- [JavaScript For Beginners: the ‘new’ operator – codeburst](https://codeburst.io/javascript-for-beginners-the-new-operator-cee35beb669e)
- [instanceof - JavaScript リダイレクト 1 | MDN](https://developer.mozilla.org/ja/docs/JavaScript/Reference/Operators/instanceof)