JavaScript きほんとか雑多なめも


# 書く場所
大きくは 3パターンあるが処理が煩雑になるので "html に固めてかく" or "html の外にかく" が良いと思う
- html に直接かく(各タグ内)
- html に固めてかく(scriptタグは1箇所のみ)
- html の外にかく（js ファイル）

### html に直接かく
```html
<!doctype html>
<html>
<head>・・</head>
<body>
    <header>・・</header>
    <main>
        <script>
            <!-- JavaScriptをここに記述 -->
        </script>
    </main>
    <footer>・・</footer>
</body>
</html>
```
### html に固めてかく
```html
<!doctype html>
<html>
<head>・・</head>
<body>
    <header>・・</header>
    <main>・・</main>
    <footer>・・</footer>
</body>
<script>
    <!-- JavaScriptをここに記述 -->
</script>
</html>
```
### html の外にかく
```html
<!doctype html>
<html>
<head>・・</head>
<body>
    <header>・・</header>
    <main>・・</main>
    <footer>・・</footer>
</body>
<!-- JavaScriptを xxx.js に記述 -->
<script src="xxx.js"></script>
</html>
```

# 変数宣言 
let, const を使うことが推奨されてる
var を使うと再宣言できたりブロックまたがってしまうので何が入ってるか見えづらい。。
基本的には const 使って変数の値を変えたいときは let を使う
### let, const, (非推奨 var)
```JavaScript
let x = 11;  // 型宣言がない, x に対してなんでも入ってしまう。。
const X = 11; // 定数宣言で代入するとエラー、配列を定数にすると中身は変えれるので注意

// 非推奨 : 宣言としてあるが使わないほうが無難（再宣言できたりでバグの温床になりやすい）
var n = 11; // ブロック内に閉じないので function で宣言するとバグりやすい。。
```

# 型
型を列挙
JavaScript だと変数宣言では型を指定できない

### 型の一覧
|分類|データ型  |用途  |
|---|---|---|
|基本(プリミティブ)|Number   |数値型、計算などに使用, NaN(Not-a-Number) は数値型の一つ(数字にできなかった数値型の特殊値, 非数)|
|基本(プリミティブ)|Boolean  |論理型、true/falseで条件分岐などに使用|
|基本(プリミティブ)|String   |文字列型、表示など多岐に使用|
|基本(プリミティブ)|undefined|何も設定してないないこと、初期化された状態|
|基本(プリミティブ)|null     |何も設定されてないこと、無・空の状態|
|基本(プリミティブ)|Bigint   |Numberを超えた値を使うとき、末尾にnつける|
|基本(プリミティブ)|Symbol   |動的に無名の一意の値になる、最近増えた(ES2015)。。。|
|参照型|Object   |JavaScriptでもクラスとか使えます|
|参照型|array   |配列型、データの入れ物|
|参照型|function   |関数、処理を入れることもできる () つけないで変数に入れたり、直接その場で関数を入れたり|

### 型の確認, その他
```JavaScript
// 型の確認方法
typeof(変数名);

// 型が違うときの注意（文字列、数値の演算子）
let x1 = 100;
let x2 = ‘100’;
console.log ( x1 + x2 ) ; // 100100 -> 文字列として扱われる
console.log ( x1 + parseInt ( x2 ) ) ; // 200 -> 数として計算したいときは数値変換してから
```

# 演算子
演算子は様々なものがあるがここでは算術演算子、比較演算子(if文で使う)に絞って記載
ビット演算、シフト演算は苦手です。。。

### 算術演算子、比較演算子いろいろ
|名称|演算子  |目的  |例  |
|---|---|---|---|
|プラス|+|足し算、文字連結|let x = 1 + 2; // 3|
|マイナス|-|引き算|let x = 3 - 1; // 2|
|乗算|*|掛け算|let x = 3 * 2; // 6|
|除算|/|割り算|let x = 6 / 3; // 2|
|剰余算|%|割り算の余り|let x = 7 / 3; // 1|
|べき乗|**|べき乗|let x = 2 ** 4; // 16|
|インクリメント|++|後(num++; 評価してから加算), 前(++num; 加算してから評価)で違うので注意|let x = 1;<br> console.log(x++);<br>// => log は1, x は2になる<br>let x = 1; <br>console.log(++x);<br>// => log は2, x も2になる|
|デクリメント|--|後(num--; 評価してから減算), 前(--num; 減算してから評価)で違うので注意|let x = 1;<br> console.log(x--);<br>// => log は1, x は0になる<br>let x = 1; <br>console.log(--x);<br>// => log は0, x も0になる|
|厳密等価|===|同じ基本型、同じ値の時に true, 比較対象がオブジェクトの時は参照が一致で true|let x = 1 === 1; // true<br>let x = 1 === '1'; // false<br> <br> let objX1 = {}, objX2={}; <br>let x = objX1 === objX2; // false<br><br>// objX1 同士の比較や objX2 に objX1 を代入した場合は true|
|等価|==|基本型は同じ値の時に true, 比較対象がオブジェクトの時は厳密等価と同様|let x = 1 == 1; // true<br>let x = 1 == '1'; // true(この結果は違う)|
|厳密不等価|!==|厳密等価の反対の結果を返す|let x = 1 !== 1; // false<br>let x = 1 !== '1'; // true|
|不等価|!=|等価の反対の結果を返す|let x = 1 != 1; // false<br>let x = 1 != '1'; // false|
|大なり|>|左が大きい場合に true|let x = 4 > 2; // true|
|以上|>=|左が以上の場合に true|let x = 2 >= 2; // true|
|小なり|<|左が小さい場合に true|let x = 4 < 2; // false|
|以下|>=|左が以下の場合に true|let x = 2 <= 2; // true|
|AND|&&|A かつ B が true なら true(どちらかが false なら false, A から評価して false なら B は評価しない)|let x = true && true; // true|
|OR|\|\||A または B が true なら true(両方とも false なら false, A から評価して true なら B は評価しない)|let x = false \|\| true; // true|
|NOT|!|評価結果を反転して true / false を返す|let x = !false; // true|

### 等価 == , 不等価 != の注意点
等価、不等価は異なる型の値であったときに暗黙的な型変換してから比較になるので予測が難しい。。。
ちょっと感覚とずれた結果が返ってくることがある。。。
```JavaScript
// 文字列を数値に変換してから比較になる。。
let x = 1 == '01'; // => true
// 真偽値を数値に変換してから比較になる。。false 0, true 1
let x = 0 == false; // => true

// nullとundefinedの比較はtrueになる
let x = null == undefined; // => true

// NaN と NaN の比較はfalse ※ これだけ厳密等価 === も同じ結果で false
let x = NaN == NaN; // => false

```

### NOT ! の存在チェック(null, undefined, NaN, false, 0, 空文字 etc)
! で存在チェックをすることがよくある
ただ Number の 0, String の 空文字 など感覚とずれた結果が返ってくるので注意が必要
```JavaScript
// true になるもの
console.log(!null);
console.log(!undefined);
console.log(!NaN);
console.log(!Infinity);
console.log(!false);
console.log(!0);   // false にならない。。。
console.log(!'');  // false にならない。。。
```

# テンプレート文字列
文字列の中で変数、数式、関数とか使いたいときにテンプレート文字列が使える
<code>`</code> (バッククォート) で囲んで変数、数式、関数は <code>${・・・}</code> で書く 

### 変数、数式使用
```JavaScript
const num1 = 5;
const num2 = 2;
console.log(`${num1} + ${num2} = ${num1+num2}`); // 「5 + 2 = 7」 が出力
```

### 変数使用
```JavaScript
const ymd = [2021, 7, 7];
console.log(`日付は${ymd[0]}年${ymd[1]}月${ymd[2]}日です`); // 「日付は2021年7月7日です」が出力
```

# if 文
if 文は Java と同じ、AND `&&` ・ OR `||` が使える
else if で複数条件を書くことができる
```JavaScript
let x = Math.random()*10;
if (x >= 3 && x <= 5) {
    // 条件満たしたときの処理
} else if (x <= 1 || x >= 9) {
    // 上記以外かつ条件満たしたときの処理
} else {
    // 上記以外の時の処理
}
```

# switch 文
switch 文は Java と同じ、変数の値の一致で分岐
`break` しない時は処理を抜けないので注意
```JavaScript
let x = parseInt(Math.random() * 10);
switch (xx) {
    case 1:
        // 1の時の処理
        break;
    case 2:
    case 3:
        // 2, 3 の時の処理
        break;
    default:
        // break しない時の処理(基本的には最後に default を書く)
        break;
}
```

# for 文
for 文 の4パターンを配列、連想配列で書き方を確認
`continue`, `break` は使えるのと使えないのがある

### for 初期値; 条件; 式
配列関係なく使える
```JavaScript
let array = [...Array(9).keys()];
for (let i = 0; i < array.length; i++) {
    console.log('for : ' + array[i]);
}
```

### continue, break
for 文でつかえる、forEach, map とか関数型のやつは使えない
```JavaScript
for (let i = 0; i < array.length; i++) {
    if (i % 2 === 0) {
        continue;  // 偶数の時は処理しないで次のループへ
    } else if (i == 8) {
        break;     // 8の時は処理しないでループ終了
    }
    console.log('for : ' + array[i]);
}
```

### forEach
連想配列だと enttries で使うのがよさそう
```JavaScript
let array = ['a', 'b', 'c', 'd', 'e'];
array.forEach((v, i) => { // v に値、i に index
    console.log('forEach : v = ' + v + ', i = ' + i);
});

let hash = { 'key1':'valueA', 'key2':'valueB', 'key3':'valueC' };
Object.keys(hash).forEach((k) => { // key 配列にしてから処理
    console.log('forEach Object.keys : k = ' + k + ', hash[k] = ' + hash[k]);
});
Object.values(hash).forEach((v) => { // value 配列にしてから処理
    console.log('forEach Object.values : v = ' + v);
});
Object.entries(hash).forEach(([k, v]) => { // entry 配列にしてから処理
    console.log('forEach Object.entries : k = ' + k + ', v = ' + v);
});

```

### for of
forEach に近い使い方, 配列の value がとれるイメージ
```JavaScript
let array = ['a', 'b', 'c', 'd', 'e'];
for (const v of array) { // v に値
    console.log('for of : v = ' + v);
}

let hash = { 'key1':'valueA', 'key2':'valueB', 'key3':'valueC' };
for (const k of Object.keys(hash)) { // key 配列にしてから処理
    console.log('for of Object.keys : k = ' + k + ', hash[k] = ' + hash[k]);
}
for (const v of Object.values(hash)) { // value 配列にしてから処理
    console.log('for of Object.values : v = ' + v);
}
for (const [k, v] of Object.entries(hash)) { // entry 配列にしてから処理
    console.log('for of Object.entries : k = ' + k + ', v = ' + v);
}
```

### for in
配列のkeyがとれるイメージ、通常の配列も暗黙的に連番の key が入ってるととらえれば。。
```JavaScript
let array = ['a', 'b', 'c', 'd', 'e'];
for (const i in array) { // i に index
    console.log('for in : i = ' + i + ', array[i] = ' + array[i]);
}

let hash = { key1:valueA, key2:valueB, key3:valueC };
for (const k in hash) { // k に key
    console.log('for in : k = ' + k + ', hash[k] = ' + hash[k]);
}
```

# while 文
while 文は Java と同じ、条件に関しては if 文と同様
前判定・後判定の2つがある
`continue`, `break` は使えるのと使えないのがある

```JavaScript
let x1 = 0;
while (x1++ < 10) {
    // 繰り返し実行する処理
}

let x2 = 0;
do {
    // 繰り返し実行する処理
} while (x2++ < 10)

let x3 = 0;
while (x3++ < 10) {
    if (x3 % 2 === 0) {
        continue;  // 偶数の時は処理しないで次のループへ
    } else if (x3 == 8) {
        break;     // 8の時は処理しないでループ終了
    }
    // 繰り返し実行する処理
}
```

# 配列(Array)
配列の宣言方法など
多次元にしたいときは `[[],[]]`としていく

### 配列宣言
```JavaScript
// 初期値あり
let array1 = [1, 2, 3, 4, 5, 6];
let array2 = new Array(1, 2, 3, 4, 5, 6) ;
// 空配列
let array3 = [];
let array4 = new Array();
let array5 = new Array(6);
// 多次元配列
let array6 = [[1, 2, 3], [4, 5, 6]];
// 連番配列の設定(1,2...9)
let array7 = [...Array(9).keys()].map(i => ++i);
```

### 配列の値取得・追加・削除
```JavaScript
let array1 = [1, 2, 3, 4, 5, 6];

// 配列の値取得
consol.log(array1[0]);

// 配列の追加
array1.push(7);
array1.unshift(10);

// 配列の削除（取り出し）
array1.pop();
array1.shift();
```

### 配列操作(filter, map, reduce, find)
```JavaScript
let array1 = [1, 2, 3, 4, 5, 6];

// 配列のフィルタ
array1.filter(i => i % 2 == 0); // [2, 4, 6]

// 配列の変換
array1.map(i => i * 50); // [50, 100, 150, 200, 250, 300]

// 配列の合計値(配列の要素を処理しながらまとめる)
array1.reduce((porcResult, currVal) => porcResult + currVal); // 総和が求まる 21

// 配列の検索(最初に一致した値を取得)
array1.find(i => i > 3); // 4

```

# 連想配列
連想配列の宣言方法など
値に配列, 連想配列の設定も可能で `{key1:{key11:value1,key12:value2},key2:[value21, value22]}` としていく
JSON は連想配列と同様の構造になる
全体に対して処理したいときは `Object.keys(hash), Object.values(hash), Object.entries(hash)` などで配列に変換してから処理することが多い

### 連想配列宣言
```JavaScript
// 初期値あり
let hash1 = { key1: 1, key2: 2, key3: 3, key4: 4, key5: 5, key6: 6};
// 空連想配列
let hash2 = {};
// 多次元連想配列
let hash3 = { key1: [1,2,3], key2: {key21: 11, key22: 12, key23: 13}};
```
### 連想配列の値取得・追加・削除・key存在確認
```JavaScript
let hash1 = { key1: 1, key2: 2, key3: 3, key4: 4, key5: 5, key6: 6};

// 連想配列の値取得
console.log(hash1['key1']);
console.log(hash1.key1);

// 連想配列の追加
hash1['key10'] = 10;
hash1.key11 = 11;

// 連想配列の削除
delete hash1['key10'];
delete hash1.key11;

// key の存在確認
console.log('key1' in hash1);
```
### 連想配列でメソッド定義(Utilクラスもどき)
JavaScript だと変数に関数が設定できることもありUtilクラスもどきが作れる
やってよいかは．．．思い付いたので備忘録．．．

```JavaScript
// キー がメソッド名、値が 処理 になる 
let hashX = { 
    method1: (a) => console.log(a), 
    method2: (a) => alert(a)
};
// メソッド実行
hashX.method1(100);
hashX.method2(100);
```
### 階層の深いJSON(連想配列)の値取得の参考
例として階層深かったり配列が入り混じってるJSON(連想配列)の値取得の参考
連想配列 `{}` と 配列 `[]` の違いに着目する必要あり
連想配列は `.` または `['key']` 、配列は `[添字]` で指定
```JavaScript
const json = {
    "results": [
        {
            "gender": "male",
			"location": {
				"street": {
					"number": 3006,
					"name": "Newjolankatu"
				},
				"postcode": 25699,
			},
        },
		{
			"gender": "male",
			"location": {
				"street": {
					"number": 9006,
					"name": "Reijolankatu"
				},
				"postcode": 43387,
			},
		}
    ],
    "info": {
        "seed": "41d21b2289902466",
    }
}

// results の 0 番目 の location の number
console.log(json.results[0].location.number);
console.log(json['results'][0]['location']['number']);
```

# スプレッド構文
配列、連想配列のコピー、結合などで使える
スプレッド構文(`...array`) はいろんな使い道がある

### 配列コピー、結合
```JavaScript
let array1 = [1, 2, 3, 4, 5, 6];
// 配列コピー
let array2 = [...array1]; // [1, 2, 3, 4, 5, 6]
// 配列結合
let array3 = [...array1, ...array2]; // [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
```

### 連想配列コピー、結合
```JavaScript
let hash1 = { key1: 1, key2: 2};
let hash2 = { key3: 3, key4: 4};
// 連想配列コピー
let hash3 = {...hash1}; // { key1: 1, key2: 2}
// 連想配列結合
let hash4 = {...hash1, ...hash2}; // { key1: 1, key2: 2, key3: 3, key4: 4 }
```

# 関数(function)
JavaScript の関数の宣言方法など
関数を変数に設定して使うこともできる
あと呼び出し関数使う時に `()` をつけないことで関数を引数として設定できる
関数に `()` つけるとその場で実行される
呼び出し側は引数があってもなくても実行できる（エラーにならない）

### 関数宣言
引数、戻り値などは必要に応じて使える
引数に初期値を設定することが可能
```JavaScript
// 引数、戻り値なしの関数
function func1() {
    console.log('func1');
}

// 引数あり、戻り値ありの関数
function func2(arg1, arg2) {
    console.log('func2' + '引数 arg1=' + arg1 + ' : arg2=' + arg2);
    return arg1 + arg2;
}

// 引数あり（初期値あり）、戻り値ありの関数
function func3(arg1='初期値1', arg2='初期値2') {
    console.log('func3' + '引数 arg1=' + arg1 + ' : arg2=' + arg2);
    return arg1 + arg2;
}

// 引数あり（可変長引数）、戻り値ありの関数
function func4(...args) {
    console.log('func4' + '引数 arg1=' + args);
    return args.join();
}

```

### 関数宣言のいろんな方法
3つの方法がありそう, どれも動きとしては同じになるかも
```JavaScript
function func1_1() {
    console.log('func1_1');
}
let func1_2 = function () {
    console.log('func1_2');
}
let func1_3 = () => {
    console.log('func1_3');
}
```
# DOM(Document Object Model)
DOM(Document Object Model) はWebブラウザのドキュメント(主にhtml)のオブジェクト
Webページを操作（追加・変更・削除）するときにつかう

### DOM取得
getElement, querySelector の2種類ある
querySelector は CSS と同じ方法で指定できる

|取得関数|戻り値|備考|
|---|---|---|
|getElementById(id)|HtmlElement (一つ)|id に一致する一番最初のもの, ない時は null|
|getElementsByClassName(class)|HTMLCollection (複数)|class に一致するもの, ない時は空のCollection|
|getElementsByTagName(tag)|HTMLCollection (複数)|tag に一致するもの, ない時は空のCollection|
|querySelector(selector)|HtmlElement (一つ)|selector に一致する一番最初のもの, ない時は null|
|querySelectorAll(selector)|NodeList(複数)|selector に一致するもの, ない時は空のList|

#### querySelector の引数 selector
代表例としてid, class, tag の記載方法
CSSと同じになるので細かく指定できる（擬似クラスは使えない．．．）
```JavaScript
document.querySelector('#aaa'); // id
document.querySelector('.aaa'); // class
document.querySelector('aaa');  // tag
```

#### HtmlCollection, NodeList の処理方法
NodeList, HtmlCollection 共に、配列に変換してからの方が処理しやすい
`Array.from` やスプレッド構文 `[...]` で配列にしてから処理するとよさそう
```JavaScript
// querySelectorAll ※ Array.from しなくてもエラーにならない
Array.from(document.querySelectorAll('div')).forEach(e => {
    console.log(e.tagName + ':' + e.textContent);
});

// getElementsByXxxName ※ Array.from しないとエラー
Array.from(document.getElementsByTagName('div')).forEach(e => {
    console.log(e.tagName + ':' + e.textContent);
});

``` 

### DOM生成
createElement で tag 指定して生成できる
表示するには生成したあとに append などで html のどこかに追加してあげる必要あり

```JavaScript
// DOM生成
let dom = document.createElement('tagName');

// DOM になんかしら設定
dom.innerText = '文字列';
// html のどこかに追加
dom.getElementById('id').append(dom);
```

### DOM要素設定・取得
取得、作成した DOM の要素の設定や取得の例
```JavaScript
let dom = document.querySelector('#id');
console.log(dom.innerText);  // テキスト取得
dom.id = 'id0'; // id の値設定
dom.style.backgroundColor = 'skyblue'; // 背景色設定
dom.style.fontSize = 20 + 'px'; // フォントサイズ設定
```



### DOM追加・削除・複製
html にある DOM を追加、削除の関数

|追加・削除・複製 関数|備考|
|---|---|
|dom1.append(dom2)|dom1 の子要素の最後に dom2 を追加する|
|dom1.prepend(dom2)|dom1 の子要素の最初に dom2 を追加する|
|dom1.insertBefore(dom2, dom3)|dom1 の子要素の dom3 の前に dom2 を追加する|
|dom1.before(dom2)|dom1 の前に dom2 を追加する|
|dom1.after(dom2)|dom1 の後に dom2 を追加する|
|dom1.remove()|dom1 を削除する|
|dom1.removeChild(dom2)|dom1 の子要素の dom2 を削除する|
|dom1.cloneNode(isDeep)|dom1 を複製する<br>引数が true は子要素含めて全て, false/なし は dom1 のみ|

# イベント
addEventListener で DOM に対してイベント追加ができる
イベント情報を持ってる `Event` を使えばいろいろな処理ができる
addEventListener で使うイベント名とDOMが持ってるプロパティにあるイベント名は少し違う（`click` と `onclick` など）

### addEventListener
```JavaScript
// イベント実行時の関数に引数として event 情報 e を設定（記載なくてもOKだが記載した方が良い）
dom.addEventListener(`eventName`, (e) => {
    // ここに処理をかく
});
```
### イベント情報(Event)
イベントの関数に引数としてイベント情報（Event）を設定できる
Event の処理を代表例としていくつか記載
```JavaScript
dom.addEventListener(`eventName`, (e) => {
    // イベント発生したDOMの取得
    event.currentTarget;
    // イベントの親への伝搬(処理)を止める（自身のイベントは継続して実行される）
    event.stopPropagation();
    // イベントの伝搬(処理)を止める（自身に対してのイベントも止める）
    event.stopImmediatePropagation();
    // イベントのデフォルト操作をキャンセル
    event.prevenDefault();
});

```

### html イベント設定
html でのイベント設定時の引数の記載方法
```html
// event がイベント情報, this が記載してるDOM
<button onclick="func(event, this)">test</button>
```

# Cookie・Web Storage
ブラウザのデータ保存として使える Cookie, Web Storage の概要を記載

|保管領域|データ量|有効期限|サーバ送信|
|---|---|---|---|
|cookie|4KB|指定期限まで|常に送信|
|local storage|5MB程度|半永久|利用時のみ|
|session storage|5MB程度|ウィンドウ、タブ閉じるまで|利用時のみ|

### Cookie の設定・取得・クリア
cookie は単純な文字列となってるので設定・取得時も文字列となる
取得は結構大変になるためライブラリ等を使った方がよさそう
```JavaScript
// cookie 設定
document.cookie = 'key1 = 値1'
document.cookie = 'key2 = 値2; max-age=10;'

// cookie 取得 
document.cookie.split(';').forEach(c => {  // ';' で分割して配列作成
    let [k, v] = c.split('=');             // '=' で分割して key, valuse の配列作成
    if (k.trim() === '取得したいキー') {   // key に空白入ってるときあるので trim して比較
        console.log(v);
    }
}

// cookie クリア ※有効期限を0にすることでクリアされる
document.cookie = 'key2 =; max-age=0;'

```

### Web storage の設定・取得・クリア
web storage は Object になっていて設定・取得・クリアの関数がある
また Object なので連想配列のように扱うこともできる
localStorage, sessionStorage とも基本的な操作は同じ
```JavaScript
// storage 設定
localStorage.setItem('key1', '値1');

// storage 取得
localStorage.getItem('key1');

// storage クリア
localStorage.removeItem('key1'); // キー指定
localStorage.clear(); // 全部
```

# Web API (Fetch API)
JavaScript から Web上の API を利用する方法として Fetch API の使い方など

### Fetch API 基本的な使い方
requestUrl に設定してるパラメータや引数の options は省略できる
レスポンス結果としてステータスコードの成功(200 ok) かどうかは確認して成功してないときはエラーとしてます
```JavaScript
    let url = 'https://sample.com';
    let requestParams = {param11:'value11', param12:'value12', };
    let postParams = {param21:'value21', param22:'value22', };
    
    let requestUrl = url + '?' + new URLSearchParams(requestParams);
    let options = {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(postParams),
        };

    fetch(requestUrl, options)
        .then(response => {
            // レスポンス結果確認
            if (!response.ok) {
                throw new Error(response.status + ':' + response.statusText);
            }
            // レスポンスから情報取得
            return response.json();
        })
        .then(json => {
            // レスポンスから取得した情報を使った処理
            console.log(json)
        })
        .catch((error) => {
            // エラー発生時の処理
            console.log(error);
            alert(error)
        });

``` 

### Fetch API の汎用関数(JSON)
基本的にはレスポンスから取得した情報の処理以外は同じ処理にすることが多い
レスポンス情報取得処理、処理例外処理を分けたいなどあればそれを引数に追加してもOK
```JavaScript
/**
 * api を実行して json を処理します
 * @param {String} url リクエストURL
 * @param {function}} functionJson json に対する処理
 * @param {Array} params リクエストURL実行時のクエリパラメータ
 * @param {Array} options リクエストURL実行時のオプション
 */
function apiJson(url, functionJson, params = {}, options = {}) {
    let requestUrl = url;
    if (!params?.length) {
        requestUrl = url + '?' + new URLSearchParams(params);
    }
    fetch(requestUrl, options)
        .then(response => {
            if (!response.ok) {
                throw new Error(response.status + ':' + response.statusText);
            }
            return response.json();
        })
        .then(json => functionJson(json))
        .catch((error) => {
            console.log(error);
            alert(error)
        });
}
```

### Fetch API async/await
async, await を使った処理の概略（参考）
関数の頭に async をつけることで非同期処理を await で待つことができる

```JavaScript
// api 実行結果を待って処理する async を付ける
async function apiExecAndProcAsync() {
    // await をつける
    let json = await apiJsonAsync('https://…');
    // json 使って処理を行う
    console.log(json);
}

// api 実行結果を返す async を付ける
async function apiJsonAsync(requestUrl, options = {}) {
    let json = await fetch(requestUrl, options)
        .then(response => {
            if (!response.ok) {
                throw new Error(response.status + ':' + response.statusText);
            }
            return response.json();
        })
        .catch((error) => {
            console.log(error);
            alert(error)
        });
    return json;
}

// エラーハンドリングとか除いた短いコード
// 関数に async つけて待つところで await をつかう
// async をつける
async function apiExecAndProcAsync() {
    // await をつける url -> response 取得
    let response = await fetch('https://…');
    // await をつける response  -> json 取得
    let json = await response.json();

    // json 使って処理できる
    console.log(json);
}

```

### Fetch API 複数非同期実行して全部待ってから処理

複数のAPIを実行して全部の結果が返ってきてから処理するときのサンプル
`Promise` を配列で持っておいて `Promise.all` で結果を取得

https://sueasen.github.io/javascript-exercise/work/promiseall/

```JavaScript
// api 実行結果を待って処理する async を付ける
async function apiMultipleExecAndProcAsync() {
    // 実行するAPI
    const urls = ['url1', 'url2', 'url3', 'url4'];
    // 実行結果 Promise 配列
    const results = new Array();
    
    for (const url of urls) {
        // json を返す Promise 設定
        results.push(fetch(url)
            .then(response => response.json())
            .catch((error) => console.log(error)));
    }

    // await Promise.all で全部の結果を待って取得
    const jsons = await Promise.all(results);

    for (const json of jsons) {
        // json 使った処理を書く
        console.log(json);
    }
}
```

# クラス利用

JavaScript でのクラスの使い方
React, Vue などフレームワーク使うと良く出てくる

### クラス定義 `export`

`export class クラス名` でクラス定義
`constructor` でコンストラクタ定義、インスタンス変数はここで `this.変数名` で定義してく感じ
関数などは必要に応じて定義

```JavaScript:クラス定義 Square.js
export class Square {
    /**
     * コンストラクタ
     * @param {Number} size 辺の長さ
     */
    constructor(size) {
        this.size = size;
    }
    /**
     * size を返します
     * @return {Number} 辺の長さ
     */
    getSize() {
        return this.size
    }
    /**
     * 面積を計算します
     * @return {Number} 面積
     */
    calcArea() {
        return this.size ** 2;
    }
}
```

### クラス参照 `import`

`import { クラス名 } from 'ファイルパス';` でクラス参照（インポート）して使う
インスタンス生成は `new クラス名()` でOK
`import { クラス名 as クラス別名 } from 'ファイルパス';` 複数ファイルから参照するときにクラス名が被ってしまう時は `クラス名 as クラス別名` で別名として使うことができる
その場合、インスタンス生成するときは `new クラス別名()` みたいになる

```JavaScript:クラス参照 script.js
import { Square } from './Square.js';

let square = new Square(5);
console.log(square.getSize());
console.log(square.calcArea());
console.log(square.size);
```

### HTML からの JavaScript読み込み

クラスを使いたいときはモジュールとして扱うので属性 `type = "module"` で読み込む必要がある

```HTML: JavaScript読み込み部分抜粋
<script src="script.js" type="module"></script>
```

# Appendix

### HTML と Script のつながり
HTML, Script で関数名, id 属性 を合わせる（src のファイルパスも忘れずに）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/fb188361-e3e0-1276-c691-81bd07b2c1ff.png)

### いろいろな参考ページ
- [DOMに動きをつける Animation (JavaScript, CSS)](https://qiita.com/sueasen/items/68040f1ad2c045edda28)
- [カルーセル（スライダー）を簡易に作ってみる](https://qiita.com/sueasen/items/0e3281a925206233c0b4)
- [モーダルを簡易につくってみる](https://qiita.com/sueasen/items/ca258566139e0cf1e5e4)
- [JavaScript で矢印キーで移動する枠をつくってみる](https://qiita.com/sueasen/items/0f40d53611ded3afedcd)
- [JavaScript 乱数使ってカラーコード生成](https://qiita.com/sueasen/items/4300043b7875b46c681f)
- [youtube動画を検索して複数いっきにみる JavaScript](https://qiita.com/sueasen/items/13c0033f3137fee397c5)
- [JavaScript 日付フォーマット、日時分秒の差分計算（週末・年末まで）](https://qiita.com/sueasen/items/d1acd9a4c784b4fb5f46)
- [JavaScript で画像・動画・音声アップロード時にプレビュー](https://qiita.com/sueasen/items/33639e98f1197393062f)
- [JavaScript で ドラッグ＆ドロップをやってみる](https://qiita.com/sueasen/items/2a39e709ffac6ff041f5)
- [JavaScript で画像・動画・音声ファイルをドラッグ＆ドロップしてプレビュー表示](https://qiita.com/sueasen/items/d342bf7b4706775de68f)
- [JavaScript でデバイスのカメラ使って撮影画像を取得](https://qiita.com/sueasen/items/5ee8c1f3351089275c20)
- [JavaScript でデバイスのカメラ使って録画した動画を取得](https://qiita.com/sueasen/items/abf2d27c888c4d6d268d)
- [css の transition, animation を使ってみる](https://qiita.com/sueasen/items/a6ba194273c234678591)
- [css で背景色を虹色でアニメーション](https://qiita.com/sueasen/items/6dfde15ee2ae59db7902)
- [VSCodeの表示言語切替の方法](https://qiita.com/sueasen/items/146faedc4152d73fdf17)
- [VSCode から ブラウザ起動 (open in browser インストール)](https://qiita.com/sueasen/items/cc88b74545499737ce8c)
- [VSCode で Webサーバ起動 (LiveServer インストール)](https://qiita.com/sueasen/items/b4fd3480be7b24b89754)