JavaScript Primerを読んだ自分用ノート

[この書籍について · JavaScript Primer #jsprimer](https://jsprimer.net/) を読んでJavaScriptを勉強したメモです。当然、原文を読んだ方が理解できます。この記事では自分が覚えたいところ、気を付けたいところだけメモしていきます。既に習得済みと私が認識している箇所は飛ばされる可能性があります。

私のスキルですが

- powershellの扱いには手馴れている
    - WebAPI叩いてコントロール、データをクラウドDBに保管したり、は出来る
    - 変数、配列…などプログラミングの基本的な考えはOK
    - オブジェクト指向はうまく使えていない
-  JavaScriptは多少触っている
    -  入りがnode.js
    -  コードをコピペして修正は出来る

です。


### JavaScript実行環境

- Webブラウザのコンソール画面で実行する
    - chromeならF12、firefoxならCtrl + Shift + K
- index.htmlからindex.jsを呼び、実行する
- consoleAPIを利用することで、Webブラウザのコンソールにprintデバッグできる
    - console.log("aaa")

### 基礎

- 変数は大文字と小文字が区別される
    - 大文字と小文字をまぜて書くのはエラーのもと
- 文の末尾はセミコロン(;)をつける
    - 最近はつけなくても動作するのでコーディングスタイル次第
- 先頭に"use strict";をつけて、strictモードを有効にする

### 変数定義・型

- 定数はconst、変数はletを使う
    - constで宣言した変数は文字列を大文字にしてletを視覚的に区別をするテクニックがある
    - カンマで変数をつなげて宣言する手にクックもある
        - count count01 = 1, count02 = 2 , count03 = 3;
        - let count11 = 1, count12 , count13;
- 型を調べたい時はconsole.log(typeof 42);などtypeofを使う
- 文字列はシングルクォート、ダブルクォートのどちらで括っても違いはない
- バッククォートで区切ると改行を認識できる。また${str}で文字列中に変数を埋め込むことができる
- オブジェクト：const obj = {};
- 配列：const arr = [];
- 正規表現：const regexp = //;

### 条件

- 比較の時は===または!==を利用する。=== → 厳密等価演算子。
- 三項演算子を使うこともできる：const valueA = true ? "A" : "B"; console.log(valueA);
- switchはbreakが必要。ifの代わりに使うのは可読性の面で良くない。

### ループ

- ループ構文：while,do-while,for,for-of(powershellのforeachと同等)
- ループ構文(メソッド)：foreach,some,filter
- 制御構文：break,continue,return

### 関数

難しかったので詳しくメモ

#### 用語

```javascript
// 関数宣言
function 関数名(仮引数1, 仮引数2) {
    // 関数を呼び出された時の処理
    // ...
    return 関数の返り値;
}
// 関数呼び出し
const 関数の結果 = 関数名(引数1, 引数2);
console.log(関数の結果); // => 関数の返り値
```

```javascript
// 関数式
const 関数名 = function() {
    // 関数を呼び出した時の処理
    // ...
    return 関数の返り値;
};
```

- 関数宣言
    - 関数を文として宣言。
    - const myfunc = fu;のような形で、文として宣言した関数を値にすることが出来る。関数式と同等。
- 関数式
    - 関数を値として定義。const = 値と同じ形
- 仮引数
    - カンマ区切りで複数定義できる
    - 呼び出しの時に指定がない場合、undefinedとなる
    - undefinedの時に設定する引数であるデフォルト引数を定義できる
    - 残余引数(...args)を指定すると、全ての引数を受け取れる
- 関数の返り値
    - return文で定義。文が実行されると後続処理は実行されない。
    - return文はなくてもOK。

#### 関数式と匿名関数とアロー関数

先ほどの説明では関数宣言と関数式を同等に覚える存在として扱ったが、近年のJavaScriptでは関数式を理解する重要度が増している。理由としては

- 非同期処理を実現する時に頻繁に利用する
- 関数宣言は多言語と同じ機能だが、関数式はJavaScript専用の理解が必要

だと思われる。

#### 関数式と匿名関数

以下が標準的な関数式であるが、この関数式では関数名 = 変数名であり、本来関数名を定義する"この部分で関数名を宣言"は省略されている。

```javascript
// 関数式
const 関数名 = function この部分で関数名を宣言() {
    // 関数を呼び出した時の処理
    // ...
    return 関数の返り値;
};
```

理由は、関数を利用したい場合は、関数名 = 変数名を利用すればよく、本来の関数名を宣言する必要がないため、省略可能である(※)。これを無名関数、匿名関数という。

※ 関数の中で関数を呼び出す場合は必要

#### アロー関数

関数式をさらに省略して記載できるのがアロー関数である。"アロー関数"と書かれているが記法だけの違いであり、機能としては関数式と同等だが、記載のしやすさ、見通しのよさより、関数式を利用する場合は、こちらの書き方が標準的になっている。

```javascript

// 通常の関数式
const 関数名 = function() {
    // 関数を呼び出した時の処理
    // ...
    return 関数の返り値;
};

// Arrow Functionを使った関数定義
const 関数名 = () => {
    // 関数を呼び出した時の処理
    // ...
    return 関数の返す値;
};
```

以下の記法を利用し、さらにこれを省略して記載できる。

- 引数記載の省略
    - 関数の仮引数が1つのときは()を省略できる
- 関数記載の省略
    - 関数の処理が1つの式である場合に、ブロックとreturn文を省略できる(その式の評価結果をreturnの返り値とする)

```javascript
// 引数記載の省略(以下の記載は同等の意味)
const fnA = (x) => {  };
const fnA = x   => {  };

// 関数記載の省略
const mulA = x => { return x * x; };
const mulB = x => x * x;
```

#### スコープ

- ブロックスコープ
    - {}の間に定義した変数は、そのスコープか下位のスコープでしか使えない
    - 自身のスコープより上位で定義された変数がある場合、それを利用できる
    - ただし、自身のスコープで同名の変数を定義した場合、その値が優先される(スコープチェーンの考え方)
- グローバルスコープ
    - スクリプトに素で定義した定数は、最上位のスコープで定義しているため、全てのスコープで利用できる
    - バグの混入を防ぐため、近年のプログラミングのセオリーでは最低限のスコープに対して変数を定義する事が推奨される
    - よって、特に理由がない限り、グローバルスコープに対して変数を定義すべきではない
- クロージャー
    - スコープチェーンと静的スコープを利用して、関数に状態を持たせるテクニック

#### 巻き上げ

どこで変数を宣言しても、スクリプトの0行目で宣言したのと同じことになる動作。varと関数宣言で動作する。便利なようで、varの場合は巻き上げによる動作が予測しづらいため、varを使うのが非推奨である理由の一つ。関数宣言はむしろ便利に使える。

#### thisについて

- function関数で使われるthisは呼び出し方によって参照する値が違い、動的である。混乱の元。
- アロー関数で使われるthisは常に1つ外側のオブジェクトを参照するため、静的である。直感的に使え、コードの見通しがよい。
- よってthisはアロー関数でしか使わないか、全く使わない方がよい。

function関数とthisの必要可否については[イマドキのJavaScriptの書き方2018 - Qiita](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)でも議論されているので、上級者視点でもメリットデメリットがありそう。

#### オブジェクト関係(オブジェクト、文字列、配列)

全てがオブジェクト、と考えればよい。文字列や配列も親となるクラスはオブジェクト。文字列や配列でできる事はpowershellと大差ない。

- プロパティ名に変数を指定したい場合はプラケット記法([xxx])
- 正規表現に変数を使用したい場合は、リテラル(/xxx/)ではなく、RegExpコンストラクタを使う
- 存在しない属性はundefinedが返ってくるが文字列と区別がつかないため、inやhasOwnPropertyを使う

### 非同期処理とコールバック

一番ムズい所なのでここでは(この短文では)纏められない。いったん理解したことにして先に進む。

- [JavaScript Promiseの本](https://azu.github.io/promises-book/)
- [JavaScriptの「コールバック関数」とは一体なんなのか](https://sbfl.net/blog/2019/02/08/javascript-callback-func/)
- [同期、非同期、Promise  |  Firebase](https://firebase.google.com/docs/functions/terminate-functions?hl=ja)
- [Promiseと仲良くなって気持ち良く非同期処理を書こう - Qiita](https://qiita.com/progre/items/03626b7f4655007d8cb2)

### 例外処理

- try
- catch
- finally
- throw
    - Errorオブジェクトで投げる
- console.logとconsole.errorを使い分ける

### Map/Set

- Map：いわゆるハッシュ、連想配列
- Set：重複した値を持たない配列。配列と違って順序の概念がないため、インデックスによるアクセスはできない。

### JSON

- Json.parse：文字列としてのJSONをJavaScriptのオブジェクトにする
- Json.stringify：オブジェクトをJSON文字列に変換する

### Date(日付時刻)

Dateが標準モジュールだが、時間を進める戻すなどできないので、他のライブラリも使って実現する事(moment.jsなど)

### ECMAScriptモジュール

- 他のJSから他のJSに変数や関数をエクスポートできる。
- エクスポート：export [エクスポートする内容]
- インポート：import [インポートする内容] from "ファイル名"

### その他メモ

- [現代の JavaScript チュートリアル](https://ja.javascript.info/)
    - 網羅的なもの
- [イマドキのJavaScriptの書き方2018 - Qiita](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
    - 非推奨な書き方を提示してくれているので、自分が新たに書き始めるときに覚えなくていいやり方を選別できる