JavaScript Primer 

https://jsprimer.net/basic/introduction/

# JavaScriptの前提

- どの実行環境でも動くものを**ECMAScript**と言う
- 大文字と小文字を区別する

``` JavaScript:JS
const name = "tuna";
// 別の変数として認識
const NAME = "tuna"; 
```

- strict mode
    - 古い構文などを禁止して安全にする実行モード
    - 明示的に書かない場合はすべてこれで実行される

``` JavaScript:JS
"use strict"; 
```

# 1.基本文法

## コメント
- 一行コメントと複数行コメントがある
``` JavaScript:JS
// 行コメント

/*
複数行コメント
複数行コメント
*/
```

## 変数宣言
- const
    - 再代入できない変数
    - 初期値を指定しなければいけない


```JavaScript:JS
const num = 10; 

// 一度に定義する場合
const a = "Java",
      b = "Script";
```
 - constは"定数"ではない
     - constで定義したオブジェクトの値などは再代入できる
```JavaScript:JS
// オブジェクトの値は初期化後でも代入できる
const object = {
    key: "値"
};

object.key = "新しい値";
```


- let
    - 再代入可能な変数
    - 初期値なしで定義可能(=undefinedになる)
```JS:JS
// 初期値なし
let num = 10;
// 初期値あり

let count = 0;

// 再代入
count = 1;
```
### 変数宣言のルール
1. 半角英字, _, $, 数字を組み合わせた名前にする
1. 数字から開始しない
1. 予約語を使わない
1. varは使わない

## 値の評価

値の評価：入力した値を評価して返すこと

## 値の評価の確認方法
### 開発者ツールのconsoleを使う
consoleに入力した値は評価されて返ってくる
```console
// 入力した値が評価され返ってくる
> 1
1
```
例）変数bookTitleを定義する
``` console
> const bookTitle = "Javascript Primer"; // 定義時はundefinedが返る
undefined

> bookTitle 
"Javascript Primer"
```
※REPL機能という

### HTMLからJavaScriptを読み込む
``` <script src="ソースのパス"></script>```で.jsファイルを読み込む

``` HTML:index.html
<html>
    <head>
    <meta charset="UTF-8">
    <title>example</title>
    <!-- JSファイル読み込み -->
    <script src="./index.js"></script> 
    </head>
    
    <body>
    </body>
</html>
```

```JS:index.js
1; // 評価はされるがconsoleには表示されない

console.log(1); // consoleAPIで表示する
```
#### console.log(引数)
コンソールに引数の評価結果を表示する
```js:JS
console.log(1 + 1); // => 2

const bookTitle = "JavaScript Primer";
console.log(bookTitle); // => "JavaScript Primer"
```

### 構文エラー
SyntaxError: missing ) after argument list (at index.js:3:13)
→構文エラー、)が足りない場合


### 実行時エラー
 ReferenceError: x is not defined
 →実行中のエラー、xが定義されていない場合

 ## データ型
 ### 前提
- JavaScriptには値の型がある
- **リテラル**とはデータを直接記述する構文
- **プリミティブ型**と**オブジェクト**合わせて7種
    - **プリミティブ型**
        - Boolean型
        - Number型
        - String型
        - null
    - **オブジェクト**
        - オブジェクト
        - 配列
        - 正規表現






型を調べる際は
console.log(typeof ~~)で調べる
```js:JS
console.log(typeof "JavaScript"); // => "string"
```



### プリミティブ型(4つ)


#### 真偽値リテラル(Boolean)
```js:JS
true;
false;
```

#### 数値型(Number) 

##### 整数リテラル(4種類)
- 10進数 ```0, 1, 2```
- 2進数  ```0b``` + ```0と1の値```
- 8進数  ```0o``` + ```0~7の値```
- 16進数 ```0x``` + ```0~fの値```

```js:JS
console.log(123); // 123
console.log(0b1111); // 15
console.log(0o10); // 8 
console.log(0xffff); // 65535
```
##### 浮動小数点リテラル
- 少数点を含む数値 ```3.1415```
- 指数を含む数値 ```2e8```
```js:JS
console.log(3.14); // 3.14
console.log(2e10); // 2^10
```
##### BigInt
- 数値リテラルの最大値2^53-1より大きな整数を扱う際に使う
- ```数値＋n```→```1n```, ```9007199254740992n```





##### 数値リテラルのNumeric Separator
桁を見やすくするために```_```で数値を分けられる
```js:JS
1_000_000_000_000;
```

#### 文字列リテラル(String)
- 文字列リテラルは``` "" ``` か``` '' ```で囲む
- 複数列の文字列は``` `` ```で囲む(テンプレートリテラル)

```js:JS
"JavaScript";

`複数の
文字列は
こう入れる`;
```

#### nullリテラル
nullは「値が無い」を示す値。
※undefinedは似ているが、リテラルではなくグローバル変数

```js:JS
const foo = null;
console.log(foo); // null
```
nullなしで空の変数を参照はできない
```js:JS
bar 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/1460500d-7bbe-026a-b3de-d475e58b38bd.png)

### オブジェクト
- キーとバリューのセットを持つもの
- キーのことを**プロパティ**と呼ぶ
- プロパティの参照は```ドット記法```,```ブラケット記法```がある


#### オブジェクトの作成と参照
```js:JS
const obj = {
    "key": "value",
    "number": 1
};

console.log(obj) // => {key: 'value', number: 1}
```

```js:JS

console.log(obj.key); // => "value" 
console.log(obj["number"]); // => 1　
```

#### 配列リテラル
配列は順序をつけて格納できるオブジェクトである
```js:JS
// 配列
const array = ["a", "b","c"];
console.log([2]); // => "c"
```



#### 正規表現リテラル
**正規表現とは**
- 文字列の組み合わせを照合するためのパターンの表記のこと。
- リテラルでは```\\```で囲む
```js:JS
const numberRegExp = /\d+/; // 一文字以上の数字
console.log(numberRegExp.test("123")) // => true 
```

#### ラッパーオブジェクト
プリミティブ型はプロパティにアクセスしようとすると自動的に**ラッパーオブジェクト**に変換される

例）文字列strに対して```str.length```で長さを調べる
```js:JS
const str = "文字列";
console.log(str.length); // => 3
```
## 演算子
- 演算を行う処理を表す
- 演算を行う対象を**オペランド**と呼ぶ

### 演算子の種類
- 二項演算子
    - ```+, -, *, /, **, %```
- 単項演算子
    - ```+1```,``` -1```
    - ```++```, ```--```
- 比較演算子
    - ```==```, ```===```, ```>, >=```など比較
- 論理演算子
    - ```&&, || ,!```などand, or, not論理演算
- ビット演算子
    - ```&, |, ^, ~```など符号付32ビット整数の演算
- 代入演算子
    - ``` = ```
- 条件(三項)演算子
   ```条件式 ? Trueのとき処理する式 : Falseのとき処理する式;```

比較と論理と三項演算のみ以下まとめる


#### 比較演算子
##### 厳密等価 ```===```
同じ型、同じ値の時trueを返す
```js:JS
console.log(1 === 1); // true
console.log("aaa" === "aaa"); // true
console.log("aaa" === "bbb"); // false
```
オブジェクトは同じ参照の時tureを返す
```js:JS
const objA = {};
const objB = {};
console.log(objA === objA); // true
console.log(objA === objB); // false
```
##### 厳密不等価 ```!==```
異なる値または異なる方のときtureを返す
```js:JS
console.log(objA !== objB); // true
```

##### 等価、不等価
基本的な挙動は厳密等価と同じだが、
- **暗黙的な型変換**をして比較する
- **null**と**undefined**を比較すると**true**が返る

あまり使うべきではない。
```js:JS
console.log(undefined == null); // true
console.log("1" == 1); //true
```


#### 論理演算子
- AND ```&&``` かつ
    - 左辺がtureなら右辺の評価結果を返す
    - 左辺がfalseなら左辺を返す

- OR  ```||``` または
    - 左辺がtrueならそのまま左辺の値を返す
    - 左辺がfalseなら右辺を返す


短絡評価＝すでに決まった値があれば次を評価しない仕組み

```js:JS
// 左辺がtrueなので、続けて右辺が評価される
true && console.log("このコンソールログは実行されます");
// 左辺がすでにfalseなので、右辺は評価されない
false && console.log("このコンソールログは実行されません");

// 左辺がすでにtrueなので、右辺は評価されない
true || console.log("このコンソールログは実行されません");
// 左辺がfalseなので、次に右辺を評価する
false || console.log("このコンソールログは実行されます");
```

#### 三項演算子
```条件式 ? Trueのとき処理する式 : Falseのとき処理する式;```
```js:JS
const valueA = true ? "a" : "b"; // ?の前がtrueなので"a"
console.log(valueA); 
const valueB = false ? "a" : "b"; // ?の前がfalseなので"b"
console.log(valueB);
```

## 暗黙的な型変換
- JavaScriptでは型変換が自動で起こる仕様がある
- ```==```や```文字列の結合```など
- 意図しない挙動に繋がるので避ける対策する
    - **明示的に型変換する**
    - **比較には```===```を使う**

```js:JS
// 暗黙的な型変換が起こる例
console.log(1 == true);  // ture
console.log(1 + "2"); // 12 
```


### 明示的な型変換の方法
#### Boolean型への変換 ```Boolean()```
```Boolean(引数)```で引数をtrueかfalseに変換する
```js:JS
const text = "abc"; 
console.log(Boolean(text)); // ture
```
##### falsyな値
暗黙的な型変換によって```false```扱いされる値を**falsy**と呼ぶ
- ```false```
- ```undefined```
- ```null```
- ```0```
- ```0n```
- ```NaN```
- ```""(空文字)```

```js:JS
let x; // undefined
if (!x) {
    console.log(x + "はfalsy");
}; // undefined はfalsy
```

より正確に真偽値を得るには```===```で比較すべし
```js:JS
let y; // undefined
if (y === undefined) {
    console.log(x + "はfalsy");
}; // undefined はfalsy
```

#### String型への変換```String()```
- ```String(引数)```で文字列に変換
- オブジェクトに対しては**使用しない**
- あくまでプリミティブ型の文字列変換
```js:JS
const z = false;
console.log(String(z)); // "false"

String(undefined); // "undefined"
```
#### 文字列→数値変換
- ```Number()```
- ```Number.parseInt()```
- ```Number.parseFloat()```

```js:JS
-// ユーザからの入力を受け取る
const input = window.prompt("数値を入力して下さい", "42");
console.log(input); // "42"または"入力文字"

// 数値に変換
const num = Number(input);
console.log(typeof num, num); // Number 42
```

```parseInt()``` ```parseFloat()```は
数字以外(undefinedも)を渡されると**NaN**を返す
```js:JS
console.log(Number.parseInt("20px")) // 20
console.log(Number.parseInt("aaa")) // NaN
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/573d69a9-3b7e-8e73-cf56-777913c97c5a.png)

##### NaN(Not a Number)とは
Number型と互換性がない値をNumberに変換すると発生する'値'(※Number型)

**何と演算しても結果がNaN**になってしまうので混入を防がなければならない

NaNの判定には```Number.isNaN()```を使う

## 関数宣言
基本の書き方
```function 関数名(仮引数1, 仮引数２...) { 処理 }```



```js:JS
// 入力を倍にする関数
function double(num)  {
    num = Number(num);
    return num * 2;
}

// windowで入力 → console出力
const input = window.prompt("数値を入力して下さい");
console.log(double(input));
```

- ```return``` 関数の実行結果を返す
- 省略か処理を書かない場合は**undefined**を返す
- 引数が少ないときは**余った仮引数にundefined**が入る

```js:JS
function func1() {}
console.log(func1()); // undefined

function func2() {
  return;
}
console.log(func2()) // undefined
```
引数が余る場合
```js:JS
function argumentsToArray(x, y) {
  return [x, y];
}
console.log(argumentsToArray(1)); // [1, undefined]
```

### デフォルト引数
仮引数に値が与えられない時の引数
```function 関数名 (仮引数=デフォルト引数) {}```
```js:JS
// デフォルト引数
function addPrefix(text, prefix = "デフォルト:") {
    return prefix + text;
}
console.log(addPrefix("aaa", "カスタム:"));
console.log(addPrefix("aaa"));
```

### 可変長引数
- 任意の数を受け取れる引数
- 書き方は  ```(...仮引数)```
- スコープ内で```仮引数```と書き、入力の**配列**を受け取る
```js:JS
function fn(...arg) {
    //　argsに配列として入る
    console.log(arg);
}
fn("a", "b", "c"); // ["a", "b", "c"]
```
複数の仮引数と使える
```js:JS
function fn(arg1, ...args) {
    console.log(arg1); // "a"
    console.log( args); // ["b", "c", "d"]
}
fn("a", "b", "c", "d"); 
```

### Spread構文 配列の展開
- ```関数(...配列)```というように渡す
- 展開されて引数に渡される

```js:JS
// Spread構文 配列を展開して関数に渡す
function fn(x, y, z) {
  console.log(x);
  console.log(y);
  console.log(z);
}

const array = [1, 2, 3];
fn(...array); // 1 2 3 
```

### 分割代入(Destructuring assignment)
- ```const {プロパティ名} = オブジェクト```で
- ```プロパティ名の変数``` に同じプロパティ名のプロパティ値が入れられる
- 一気に変数に入れられるので便利

分割代入ナシ
```js:JS
const user = {
    "id":"123",
    "userName": "Taro"
} 
const id = user.id; // idに"123"
const userName = user.userName; // userNameに"Taro"

console.log(id);
console.log(userName);
```

分割代入アリ
```js:JS
const user = {
    "id":"123",
    "userName": "Taro"
} 
const {id, userName} = user; // idに"123", userNameに"Taro"が入る

console.log(id);
console.log(userName);
```

### 関数での分割代入
- ```function 関数名({ プロパティ名 }) {}```
- オブジェクトのプロパティ名の値を**仮引数**として受け取る
```js:JS
// userオブジェクトのidプロパティの値を仮引数idとして受け取る
function printUserId({ id }) { 
    console.log(id)
}

printUserId(user); // "123"
```


関数の分割代入は**```[配列]```**もできる
```js:JS
function print([first, second]) {
```

## 関数式
- 関数はオブジェクトなので、**値**としても扱える(第一級関数"ファーストクラスファンクション"という)
- 式なので変数に入れたりできる
- **関数式**は```function```や```Arrow Function```で定義する

### 関数式の書き方① **```変数名 = function() {};```**
**```const 変数名 = function() {};```**
**```const 変数名 = function 関数式名() {};```**

- 関数式は**関数名を省略**できる
- 名前を持たない関数を**無名関数**という
- 再帰的に関数を呼び出す場合などに使う(外部から呼ぶ必要がないから)

```js:JS
//　無名の再帰関数(0になるまで１引いて前の数値と掛け算)
const factional = function innerFact(n) {
    if (n === 0) {
        return 1;
    }
    return n * innerFact(n - 1);
};

console.log(factional(3)); // 6
```

### 関数式の書き方② ```関数名 = () => {};```
**```const 変数名 = (仮引数) => {return 返り値}; ```**
**```const 変数名 = () => {}; ```** 
- **Arrow Fancrion**という書き方
- =>を使い無名関数を定義する
- 省略記法を使って短く記述できる

```js:JS
// Arrow Function
const fnA = () => {};

const fnB = x => {x * 2}; // 引数が1つなら()を省略可
const fnC = x => x * 2;  // 一行なら{ブロック}も省略可
```
**特徴**
- ```this```が静的に決定
- ```new```できない
- ```arguments```を参照できない

#### コールバック関数
- 関数に**引数として**渡される関数
- コールバック関数を引数に使う関数・メソッドを**高階関数**と呼ぶ
- 非同期処理でよく利用する
```js:JS
// コールバック関数
const array2 = [1, 2, 3];
const output  = (value) => {
    console.log(value);
} ;

array2.forEach(output); // 

// コールバック関数を直接引数として定義する
const array3 = [1, 2, 3];
array3.forEach(value => {
    console.log(value);
});
```

### メソッド
- オブジェクトがプロパティとして持つ関数のこと
- 定義 : ```{メソッド名 : function(){処理}}```
- 呼出 : ```オブジェクト.メソッド名()```

```js:JS
// メソッド
const objC = {
  method1: function () {
    // メソッド1の処理
  },
  method2: function () {
    // メソッド2の処理
  }
};
```
呼び出し
```js:JS
const objHello = {
  funcHello: function () {
    console.log("Hello World");
  }
};

objHello.funcHello(); // メソッドfuncHelloを呼ぶ
```

#### メソッドの短縮記法(基本これで書く)
- ES2015より基本となった書き方
- オブジェクトリテラル```{}```の中に
- **```{ メソッド名() {処理} };```**

```js:JS
// メソッドの短縮記法
const obj = {
  method() { // メソッド名 ()
    return "this is method";
  },
};
console.log(obj.method());
```

## 式と文
JavaScriptプログラムは式と文からできている

### 式(Expression)
- 値を生成し変数に代入できるもの
- 式を評価すると**評価値**が得られる
- リテラルや関数式、```1 + 1```などの演算も式

```js:JS
console.log(1); // 1という数値リテラル(式)
console.log(1 + 1); // 1 + 1(式)の評価値は2


const fn = function() { // 関数式も式の一つ
    return "hello";
};
```


### 文(Statement)
- 処理する一ステップのことでセミコロン```; ```で区切る
- ```for文```や```if文```など文のひとつ
- 式は文になれる→**式文**

### 式文
- 文を書ける場所には式を書ける
- **文となった式**を**式文**という

#### 関数宣言と関数式の違い
- 関数宣言は**文**
- 関数式は**式**(```; ```をつける)
```js:JS
function learn(){ // 関数宣言
}

const read = function() { // 関数式
};
```
## 条件分岐
- if文やfor文
- 条件によって処理を切り替える

### if文
- **```if (条件式) {処理}```**
- ```(条件式)```が```True```のとき処理される
- **falsy**な値は```False```と判断される

```js:JS
if ([]) {
  console.log("配列はTrue");
}
if ({}) {
  console.log("オブジェクトはtrue");
}
if ("もじ") {
    console.log("文字列はtrue");
}
// falsyな例
if (!"") {
    console.log("空文字はfalse");
}
if (!null) {
    console.log("nullはfalse");
}
```

### else、else if文
- 条件に一致しない部分を```else```で指定する
- 複数条件の場合```else if```と書く
```js:JS
// else else if
const version = "ES6";
if (version === "ES5") {
  console.log("ECMAScript 5");
} else if (version === "ES 6") {
  console.log("ECMAScript 2015");
} else if (version === "ES7") {
  console.log("ECMAScript 2016");
}
```

### swich case 文
- **```switch (条件式) {case1: 処理１; case2: 処理2;...}```**
- 厳密等価```===```で**条件式とcase**を比較
- 一致したら処理する
- 必ず**break**をセットで使う(関数の処理内ならば**return**でも良い)


```js:JS
- switch ("jp") {
  case "jp":
    console.log("こんにちは");
    break;
  case "us":
    console.log("Hello");
    break;
  case "cn":
    console.log("你好");
    break;
  default:// どの条件にも合致しない時
    break; 
}
```

## ループ 反復処理

### while文
- 条件式の評価値が```true```なら**反復処理**をする
- 条件式が```false```になったとき処理を抜ける
- **```while (条件式){ 処理 }```**
```js:JS
let x = 0;
console.log(`xの初期値: ${x}`);
while (x < 10) {
  console.log(x);
  x += 1;
}

console.log(`ループ処理終了 x : ${x}`);
```

### do-while
- whileの処理が先に実行されるバージョン
- **```do { 処理 } while(条件式); ```**

```js:JS
let y = 20;
do {
  console.log(y);
  y -= 1;
} while (y > 10); // 20~11まで表示される
```

### for文
- 繰り返し範囲を指定した反復処理をかく
- **``` for (初期化式; 条件式; 増分式) { 処理 }```**

```js:JS
// forでsum関数を実装する例
function sum(numbers) {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) { // 配列の長さ分繰り返す
    total += numbers[i];
  }
  return total;
}

console.log("合計は:" + sum([1, 2, 3, 4, 5])); // => 合計は15
```

### ```forEach```: 配列の反復処理
- 配列の各要素**それぞれに**順に処理をするメソッド
- 書き方:**```配列名.forEach( 引数 => {処理});```**
- 配列の先頭から```コールバック関数の引数```に要素が入る

```js:JS
// arrayのforEach
const num_array = [1, 2, 3];
num_array.forEach(num => { // numはコールバック関数の引数
  console.log(num); // => 1, 2, 3
});
```

sum関数を**forEach**で書く例
```js:JS
// sum関数をforEachで実装する
function sum(numArray) {
  let total = 0;
  // numにnumArrayがひとつづつ入る
  total = total + num;
  numArray.forEach((num) => {});
  return total;
}

console.log("合計は:" + sum([1, 2, 3, 4, 5]));
```

### some関数
- **```配列.some(引数 => {ture/fasleを返す目関数});```**
- または```配列.some(別でfunction定義したコールバック関数);```
- **ture**が返った瞬間に反復を終了する

```js:JS
// some関数
function isEven(num) {
  return num % 2 === 0;
}
const numbers = [1, 5, 10, 15, 20];
console.log(numbers.some(isEven)); // => true
```

### filter(配列値をフィルターする) 
- **```配列.filter(コールバック関数);```**
- コールバック関数が**True**を返した要素のみを追加した新しい配列を返す

```js:JS
function isEven(num) {
  return num % 2 === 0;
}

const numbers = [1, 5, 10, 15, 20];
// isEvenがTrueの値のみnubersから取り出す
console.log(numbers.filter(isEven)) // => [10, 20]
```

## オブジェクトに対する反復処理

### for in() 
- **オブジェクトのプロパティ**に対して反復処理をする
- ※意図しないプロパティまで列挙されてしまうので、なるべく使わない方がいい
- **```for (プロパティのキー in オブジェクト) {プロパティに対する処理}```**

```js:JS
// for-inでオブジェクトのプロパティを列挙
const objA = {
  "a": 1,
  "b": 2,
  "c": 3
}

for (key in objA) {
  const value = objA[key];
  console.log(`key:${key}, value:${value}`);
} 
// key:a, value:1 
// key:b, value:2 
// key:c, value:3
```

### for of文
- **オブジェクトの値**を取り出して反復処理
- **```for(変数 of イテラブル) {処理} ```**
- イテラブルとは、**反復処理の動作が定義されたオブジェクト**のこと(配列、文字列、Map、Setなど)


```js:JS
arrayX = [1, 2, 3];

for (value of arrayX) {
  console.log(value)
}
// 1
// 2
// 3
```

## オブジェクト詳細
- オブジェクトとは**キー**と**バリュー**が対になったもの
- ```{"キー(プロパティ)": "値"};```で定義
- プロパティは```""```を省略して書ける

```js:JS
const obj = {
    "key": "balue"
};
```
```js:JS
// クオートの省略
const obj = {
    key: "balue"
};
```
変数名として利用できない記号を**キー**に含める時は```"obj-a"```の様にクオートで囲む

### オブジェクトの値の省略

- **プロパティ名**と**値に指定する変数名**が同じ場合、値を省略できる

```js:JS
const fruit = "apple";
fluits = {
  fruit
}
console.log(fluits); // {fruit: 'apple'}
```
### ```Object``` ビルドインオブジェクト 
- ＝あらゆるオブジェクトの基になる実行環境に用意されたオブジェクト
- **```new Object()```** で空のオブジェクトを作成※ ```{}(リテラル)``` と同じ

```js:JS
const newObj = new Object();
console.log(typeof newObj); // => Object
```

オブジェクトを作成するとは、
```Object```から```インスタンスオブジェクト```を作成すること。

### プロパティの参照の注意
- プロパティ名は**暗黙的に文字列に変換**される。
- ブラケット記法ではプロパティ名に**変数**を使って参照できる

```js:JS
const obj = {
    key: "value",
    123: 456,
    "my-key": "my-value"
};

console.log(obj[123]); // => 456
console.log(obj["123"]); // => 456
```

```js:JS
const languages = {
    ja: "日本語",
    en: "英語"
};

cont myLang = "ja" // 変数をキーとして参照
console.log(langages[myLang]); // 日本語
```

### 変数へオブジェクトの値を一括で入れる(分割代入)
- **分割代入**を使って変数に値を入れる
- ```const {変数1, 変数2...} = Obj; ```
- プロパティ名と同じ変数に同じ値が入る

```js:JS
const languages = {
    ja: "日本語",
    en: "英語"
};
const { ja, en } = languages;
console.log(ja); // => "日本語"
console.log(en); // => "英語"
```


### プロパティの追加
- **```オブジェクト.新しいプロパティ＝値```**
- 新しいキーとバリューを追加できる
- **むやみにプロパティを追加**するのは✖
- (なるべく最初の宣言の形を維持する)

```js:JS
const newObj = new Object();t
// newKeyと値を追加
newObj.newkey = "new value.";
console.log(newObj.newkey); //=> new value.
```

### プロパティの削除
- ```delete オブジェクト.プロパティ(キー)```
```js:JS
delete newObj.newkey;
console.log(newObj); // => {} 空になる
```

### ```Object.freeze()``` オブジェクトの固定
- オブジェクトの変更を不可にする
- **プロパティの追加削除**,**値の変更**が出来なくなる

```js:JS
// オブジェクトの値を代入不可にする
const freezeObj = Object.freeze({key: "value"});
freezeObj.key = "new value";
console.log(freezeObj.key); //=> TypeError
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/b68c88f4-ada5-de8f-2f65-f0f0392867fd.png)
```TypeError: "key" is read-only```

### プロパティの存在を確認 
- 存在しないプロパティにアクセス＝```undefined```が返り**エラーは出ない**から値が```undefined```の場合混乱する
- **```in```, ```Object.hasOwn()```**を使って確認する

### in演算子
- ```プロパティ名 in オブジェクト;```
- ```ture```か```false```が返る

```js:JS
const obj = { key: undefined };
// `key`プロパティを持っているならtrue
if ("key" in obj) {
    console.log("`key`プロパティは存在する");
}
```
### Object.hasOwn()メソッド
- ```Object.hasOwn(オブジェクト, "プロパティ");```
- 対象のプロパティが存在すれば```ture```が返る(inと同様)
```js:JS
// objに"key"プロパティが含まれるか確認
Object.hasOwn(obj, "key"); // ture false 
```


### ```?.``` Optional Chainingでプロパティの存在確認
- ネストしたプロパティは存在確認が大変
    - ```(widget.window.title) ```みたいな
- **```?.```を使ってプロパティの値を取る**
- 値が存在すれば```値```、なければその時点で```undefined```を返す

```js:JS
// ifを使ったプロパティの存在確認
 if (widget.window !== undefined && widget.window.title !== undefined) {
    //widget.windowとwidget.window.titleを順にみないといけない
};

// ?.で存在確認
widget?.window?.title; // undefinedかtitleの値が返る
```

三項演算子を使ってプロパティが定義済みか確認する例
```js:JS
function printWidgetTitle(widget) {

// widget.window.titleが定義済み=>値
// widget.window.titleが未定義=>右辺の処理
    const title = widget?.window?.title ?? "未定義";
    console.log(`ウィジェットのタイトルは${title}です`);
}
```

## オブジェクトの静的メソッド
- ```Object```ビルドインオブジェクトそのものに実装されているメソッド
- **静的メソッド(スタティックメソッド)** 
- ```toString``` ```hasOwn```など..


静的メソッドは、インスタンス元のオブジェクトから呼び出せるメソッドのことを言う。

**例）**

- ```Object.keys```: キーの列挙
- ```Object.values```: 値の列挙
- ```Object.entries```: [キー: 値]の列挙
```js:JS
const testObj = {
  one: 1,
  two: 2,
  three: 3,
};

console.log(Object.keys(testObj)); // ['one', 'two', 'three']
console.log(Object.values(testObj)); // ['one', 'two', 'three']
console.log(Object.entries(testObj)); // [["one", 1], ["two", 2], ["three", 3]]

```

### オブジェクトのマージ
- **```Object.assign(ターゲット, obj1, obj2...)```**
- オブジェクトの内容をコピーまたはマージする

```js:JS
const objectA = { a: "a" };
const objectB = { b: "b" };

// 空配列mergedにA, Bの合わせ新しく定義
const merged = Object.assign({}, objectA, objectB); // { a: "a", b: "b" }
// objAは変更されmarged===objAとなる
const merged = Object.assign(objectA, objectB);
```
```Object.assign()```を使う場合は、
ターゲットに空オブジェクトを指定すると元の配列には影響がないので、一般的に上の様にする。

#### spread構文でのマージ
```js:JS
const objX = {a: "a"};
const objY = {b: "b"};

const mearged = {
  ...objX,
  ...objY
};

console.log(mearged); // {a: "a", b: "b"}
```

### オブジェクトのコピー
- オブジェクトのコピーにも```Object.assign({}, コピー元)```として使う
```js:JS
const copyObj = Object.assign({}, obj); // コピーされる
```

#### shallow copy
assignメソッドでできるのは **shallow copy(浅いコピー)** で、
ネストされたオブジェクトは複製されない。

#### deep copy
プロパティ値まで再帰的にコピーする場合は再帰処理を用いて自分でdeep copyを実装する
- shallow copyする
- もしキーにオブジェクトがあれば再帰的にコピー
```js:JS
function deepClone(obj) {
    const newObj = shallowClone(obj);
    // プロパティがオブジェクト型であるなら、再帰的に複製する
    Object.keys(newObj)
        .filter(k => typeof newObj[k] === "object")
        .forEach(k => newObj[k] = deepClone(newObj[k]));
    return newObj;
}
```

## 配列

- JavaScriptの配列は可変長
- 値の追加や削除が出来る
    - ```push```, ```pop```
- 配列のArray.メソッドには**破壊的**と**非破壊的**メソッドがある。

### Array.length
- 配列の要素数を返す

```js:JS
// 配列のメソッド
const arrayA = [1, 2, 3];
console.log(arrayA.length); // => 3
```

### 疎な配列と密な配列
- 配列に空の要素がある配列→**疎な配列**
- 疎を参照すると```undefined```が返る

```js:JS
// 疎な配列
const arrayB = [4, , 6];
console.log(arrayB[1]) // => undefined
```
### ```Array.at(index)```:要素の参照
- 配列の要素を参照する
- ```Array.at(-1)```など負の数で後ろから参照
- (Array[Array.length -1]より楽)

```js:JS
const array = ["a", "b", "c"];
//
console.log(array.at(0)); // => "a"
console.log(array.at(1)); // => "b"
// 後ろから1つ目の要素にアクセス
console.log(array.at(-1));
```
※配列[-1]と書くと、大抵の場合はundefinedが返ってしまう(無いプロパティへのアクセス)


### ```Array.isArray(obj)```:配列かオブジェクトかの判断
- ```true``` ```false``` が返る
- ※```typeof```演算子では配列も[Object]と判定されるので判定できない

```js:JS
const obj = {};
const array = [];
console.log(Array.isArray(obj)); // => false
console.log(Array.isArray(array)); // => true
```

### 分割代入
- 配列もオブジェクト同様、分割代入が出来る

```js:JS
const arrayN = ["first", "second", "third"];
const [first, second, third] = arrayN;

console.log(first); // first
console.log(second); // second
console.log(third); // third
```

### ```hasOwn```で疎かUndefinedか判定する
- 配列は参照外、空、undefinedを参照するとどれも**undefined**が返る
- 指定したIndexが空なのかundefinedかを見分けるには
- **```Object.hasOwn(配列, index)```**
```js:JS
const arrayB = [4, , 6];
console.log(Object.hasOwn(arrayB, 1)); // false
```
falseなら要素自体が存在しない

### ```indexOf``` ```lastIndexof```：要素でインデックスを取得
- ```Array.indexOf(要素)```でインデックスの位置が返る
- 一致するものが無いとき```-1```が返る

```js:JS
const animals = ["サル", "鳥", "犬"];
const birdIndex = animals.indexOf("鳥");
console.log(birdIndex); // => 1

const fishIndex = animals.indexOf("魚")
console.log(fishIndex); // => -1
```
### ```array.find```: 条件に一致する要素を取得
- ```配列名.find(コールバック関数)```
- コールバック関数には条件を入れる
- 一致する要素そのものが返る

```js:JS
const colors = [{ color: "red" }, { color: "green" }, { color: "blue" }];

// find
const greenColor = colors.find((obj) => {
  return obj.color === "green";
});


console.log(greenColor); // {color: 'green'}


// 10より大きい`count`プロパティを持つ最初のオブジェクトを取得
const firstRecord = records.find((record) => {
    return record.count > 10;
});
console.log(firstRecord); // { date: "2020/12/2", count: 11 }
```

### ```array.findIndex```: 条件に一致するIndexを取得
- ```配列名.findIndex(コールバック関数)```
- コールバック関数には条件を入れる

```js:JS
// findIndex
const blueColor = colors.findIndex((obj) => {
  return obj.color === "blue";
});
console.log(blueColor); // 2
```

### ```Array.slise```：範囲を指定して取得
- ```配列名.slise(始点, 終点);```
- 新しい配列として範囲を取り出す
 ```js:JS
 // slise
const numArray = [1, 2, 3, 4, 5];
console.log(numArray.slice(1, 4)); // [2, 3, 4]
```
### ```Array.includes()```:要素が含まれているか
- 配列に要素が含まれている場合、```true```を返す
```js:JS
const array = ["Java", "JavaScript", "Ruby"];
// `includes`は含まれているなら`true`を返す
if (array.includes("JavaScript")) {
    console.log("配列にJavaScriptが含まれている");
}
```
## 配列への追加・削除
###  ```array.push()```末尾に追加
- ```配列名.push(追加要素)```
- 先頭への追加は
    - ```配列名.unshift(追加要素)```

### ```array.pop()```:末尾を削除
- ```配列名.pop()```
- 先頭の削除は
    - ```配列名.shift()```

```js:JS
const array = ["A", "B", "C"];
array.push("D"); // "D"を末尾に追加
console.log(array); // => ["A", "B", "C", "D"]

const poppedItem = array.pop(); // 最末尾の要素を削除し、その要素を返す
console.log(poppedItem); // => "D"
console.log(array); // => ["A", "B", "C"]
```
```js:JS
const array = ["A", "B", "C"];
array.unshift("S"); // "S"を先頭に追加
console.log(array); // => ["S", "A", "B", "C"]

const shiftedItem = array.shift(); // 先頭の要素を削除
console.log(shiftedItem); // => "S"
console.log(array); // => ["A", "B", "C"]
```

### ```array.splice()```: 任意のインデックスの追加・削除
- ```array.splice(インデックス, 削除する要素数);```
- ```array.splice(インデックス, 削除する要素数, ...追加する要素);```

```js:JS
const array = ["a", "b", "c"];
// 1番目から1つの要素("b")を削除
array.splice(1, 1);
console.log(array); // => ["a", "c"]
console.log(array.length); // => 2
console.log(array[1]); // => "c"
// すべて削除
array.splice(0, array.length);
console.log(array.length); // => 0
```

## ```array.concat()```:配列の結合
- ```結合元配列.concat(結合したい配列)```
- 合体した新しい配列が作成される
```js:JS
const array = ["A", "B", "C"];
const newArray = array.concat(["D", "E"]);
console.log(newArray); // => ["A", "B", "C", "D", "E"]
```
### ```...```: 配列の展開
- spread構文で配列を任意の位置で展開
- concatと異なりどこでも結合できる

```js:JS
const charArray = ["a", "b", "c"];
const charsArray = ["x", ...charArray, "x"];
console.log(charsArray); // ['x', 'a', 'b', 'c', 'x']
```
### ```array.flat```:配列のフラット化
- 多重の配列```[[[]]```を```[]```にする
- flat化する深さは **```array.flat(深さ)```** で指定
- 全階層フラットにする場合、引数に```Infinity```を指定する

```js:JS
const multiArray = [[[1], 2], 3];
console.log(multiArray.flat(2)); //  [1, 2, 3]
```

### ```array.length```を利用した要素削除
- 配列要素を一括削除する時、```length```プロパティに```0```を代入する
- **```array.length = 0 // []空の配列に```**

## 破壊的・非破壊的メソッド
- 配列操作には2つある
    - **Mutable(破壊的)なメソッド**
    - **immutable(非破壊的)なメソッド**
- 出来るだけ非破壊の利用が望ましい
    - 破壊的：**対象の配列自体**を操作
    - 非破壊的：**対象のコピー**を操作する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/a3f7af47-6f1c-bff3-4d68-9ec07cb4e428.png)
https://jsprimer.net/basic/array/


例)```pop``` ```push``` ```splise```→破壊的
　```.at(-1)``` ```...``` ```toSpliced```→非破壊的

 ## 配列の反復処理
 ### ```forEach```
 - 配列の要素を取出し先頭から処理する
 - 返値を返さない
 - (元の配列は操作しない)
 ```js:JS
const array = [1, 2, 3];
const doubleArray = array.forEach((value, index, array) => {
  return value * 2;
});
console.log(doubleArray); // undefined
```

 ### ```map```
 - 配列の要素を先頭から処理する
 - 処理した結果を適応した**新しい配列を返す**

```js:JS
const array = [1, 2, 3];
const doubleArray = array.map((value, index, array) => {
  return value * 2;
});
console.log(doubleArray); // [2, 4, 6]
```


 ### ```filter```
- 配列から**不要な要素を取り除く**
- コールバック関数は```true``` ```falase```を返し
- ```true```の要素だけ集めた新しい配列を返す
```js:JS

const filterArray = array.filter((num) => {
  return num % 2 == 0;
}) 

console.log(filterArray); // [2]
```

 ### ```reduce```
 - 配列要素の合計値を返す
 - ```reduce(一つ目の値, 2つ目の値) => {return 一つ目の値 + 2つ目の値}```
 - 配列の前から順に残りを足していくイメージ

 ```js:JS
 const sumValue = array.reduce((acc, curentValue) => {
  console.log(`acc:${acc}, curent:${curentValue}`);
  // acc:1, curent:2
  // acc:3, curent:3
  return acc + curentValue;
});
console.log(sumValue); // 6
```
### ```groupBy```
- 配列の要素を条件でグループ分けし新たな配列を作成する
- (フィルターとは違い**条件に合致しないものもグループ化する**)

```js:JS
const array = [1, 2, 3, 4, 5];
const grouped = Object.groupBy(array, (currentValue) => {
    // currentValueが偶数なら"even"、そうでないなら"odd"の配列に追加される
    return currentValue % 2 === 0 ? "even" : "odd";
});
console.log(grouped.even); // => [2, 4]
console.log(grouped.odd); // => [1, 3, 5]
```

## メソッドチェーン
- **```[対象].mesod1().mesod2()...```** 
- メソッドをつなげて処理を連続させること→**メソッドチェーン**という
- 簡潔に処理を書ける

```js:JS
const array = ["a"].concat("b").concat("c");
console.log(array); // => ["a", "b", "c"]
```
例)
- ```filter```で年を絞り込み
- ```map```で結果をまとめて返す
```js:JS
// ECMAScriptのバージョン名と発行年
const ECMAScriptVersions = [
    { name: "ECMAScript 1", year: 1997 },
    { name: "ECMAScript 2", year: 1998 },
    { name: "ECMAScript 3", year: 1999 },
    { name: "ECMAScript 5", year: 2009 },
    { name: "ECMAScript 5.1", year: 2011 },
    { name: "ECMAScript 2015", year: 2015 },
    { name: "ECMAScript 2016", year: 2016 },
    { name: "ECMAScript 2017", year: 2017 },
];
// メソッドチェーンで加工処理を並べる
const versionNames = ECMAScriptVersions
    // 2000年以下のデータに絞り込み
    .filter(ECMAScript => ECMAScript.year <= 2000)
    // 各要素から`name`プロパティを取り出す
    .map(ECMAScript => ECMAScript.name);
console.log(versionNames); 
// => ["ECMAScript 1", "ECMAScript 2", "ECMAScript 3"]
```

## 文字列

### 文字へのアクセス
- 配列風のアクセスと```.at()```がある
- ```文字列[index]```
- ```文字列.at(±num)```
```js:JS
// 文字列
// 配列でアクセス
const str = "ABCD";
console.log(str[1]); // B
console.log(str[2]); // C

// String.prototype.atでアクセス
console.log(str.at(0)) // A
console.log(str.at(1)) // B
console.log(str.at(-1)) // D
```
```at```はStoringプロトタイプオブジェクトのメソッド。
```carAt```というメソッドもある(```at```との違い：負のとき空文字を返す)

### 文字列の結合・分解
- ```.split("")``` ：文字列の分解
- ```.join("")``` ：文字列の結合

```js:JS
// split 文字列の分解
const strings = "赤・青・黄";
let spStr = strings.split("・");

console.log(spStr); // ["赤", "青", "黄"]
```
```js:JS
// join 文字列の結合
spStr = spStr.join("&");
console.log(spStr); // 赤&青&黄
```
同時に使うことがよくある
```js:jS
const tea = "玄米茶";
spTea = tea.split("").join("★");

console.log(spTea); // 玄★米★茶
```

#### 正規表現での```split()```
正規表現でマッチを探して```split```できる
```js:JS
// 1つ以上のスペースの正規表現➢ /\s+/
const space = "a  ba   c";
spSpace = space.split(/\s+/);

console.log(spSpace); // ['a', 'ba', 'c']
```
### 文字列の大小
JavaScriptは文字コードとしてUnicode、エンコードする方式としてUTF-16を採用している


- **文字コード**：文字を01のビットに変換したもの(Unicode)
- **エンコード**：文字コードをさらにコンピュータ用に変換すること(UTF-8, UTF-16)

https://www.javadrive.jp/javascript/string/index14.html#google_vignette

```js:JS
// CよりDが、文字コードは後ろ
console.log("ABC" > "ABD"); // => false
```
文字列は**コードユニット**の並びで、
先頭から比較される。( コードユニットは例だと3つ)

### 文字の切り出し
文字列から任意の部分を切り出す
- ```slice()```
- ```substring()```

**slice(始点,終点)**
```js:JS
const alphabet = "abcdefg";

console.log(alphabet.slice(0, 3)); // abc
console.log(alphabet.slice(2, 5)); // cde
console.log(alphabet.slice(-2)); // fg 
```
負の数は後ろから数える



**substring(始点, 終点)** ※負の数は"0"扱い
```js:JS
console.log(alphabet.substring(0)) // abcdefg
console.log(alphabet.substring(3, 5)) // de
console.log(alphabet.substring(-1)) // abcdefg
```

いずれも非破壊的なメソッドで機能の違いもないので好みで使う。

----

### 文字列の検索
- ```IndexOf()```
- ```lastIndexOf()```

**IndexOf("検索したい文字列")**
- 前方から検索して一致した**インデックス**を返す


**lastIndexOf("検索したい文字列")**
- 後方から検索して一致したインデックスを返す

```js:JS
const fruits = "ばななリンゴぶどうリンゴオレンジ";

console.log(fruits.indexOf("リンゴ")); // 3
console.log(fruits.indexOf("ぶどう")); // 6
console.log(fruits.lastIndexOf("リンゴ")); // 9 後ろ側のリンゴの先頭index
```
いずれのメソッドも一致しない場合```-1```を返す
```js:JS
console.log(fruits.indexOf("ブドウ")); // -1
console.log(fruits.lastIndexOf("ブドウ")); // -1
```

- 応用例
```js:JS
// "いちご"が無い場合、indexOfは-1を返す
if (fruits.indexOf("いちご") != -1) {
  console.log("いちごがあります！");
} else {
  console.log("いちごはありません");
}
```


### 文字列の置換
特定の文字列を**別の文字(列)に置き換える**
- ```replace()```
- ```replarceAll()```

**replace( "検索対象", "置きかえ文字")** 
**replace( /正規表現/, "置きかえ文字")**
```js:JS
// 直接指定
const phrase = "にわにはにわにわとりがいる";
console.log(phrase.replace("にわとり", "ハト"));
// => にわにはにわハトがいる

// 正規表現
console.log(phrase.replace(/にわ/g, "ハト"));
// => ハトにはハトハトとりがいる
```

----

**replaceAll("検索対象", "置きかえ文字")**

- replace()との違い
    - replace: 最初の一致しか変換しない
    - replaceAll: すべての一致を置きかえる

```js:JS
const text = "0120-117-117";
const result = text.replaceAll("-", "($&)");
console.log(result);
// => 0120(-)117(-)117
```
#### コールバック関数を用いた複雑な変換
- replace, replaceAllは第2引数にコールバック関数を渡せる
- ```repllace("対象", ()=> { 処理 });```
- ```repllaceAll("対象", ()=> { 処理 });```

複雑に年月日などの置き換えが可能
```js:JS
function toDateJa(dateString) {
  // マッチした対象のみコールバック関数で置換処理
  return dateString.replace(
    /(\d{4})-(\d{2})-(\d{2})/g,
    (all, year, month, day) => {
      // allはマッチした文字列全体が入っている(未利用)
      return `${year}年${month}月${day}日`;
    }
  );
}
console.log(toDateJa("2024-01-02")); // 2024年01月02日
```

## code point と code unit
- JavaScriptはUTF-16でエンコードした**code unit**単位で文字を認識する
- **code point** =  unicodeに対応した1文字1IDの単位(実質的な1文字)

```js:JS
// code point
const aiu = "あイウ";
console.log(aiu.codePointAt(0)); // 12354
console.log(aiu.codePointAt(1)); // 12452
// 16進数表示
console.log(aiu.codePointAt(0).toString(16)); // 3042
console.log(aiu.codePointAt(1).toString(16)); // 30a4
```

※JavaScriptは
code unitで文字を取扱うメソッドとcode pointで取扱うメソッドがある。

#### code unitの注意点
- **code unit = 1文字ではない！**
- 絵文字など複数code unitで表される文字がある
- ➢**サロゲートペア** という

```js:JS
const ringo = "🍎"
console.log(ringo.length); // 2
```
※例として🍎はlength(code *unit*)が2つ


##### code pointで数える・扱うには？
- array.from()で配列に変換する
- 正規表現で```\u{unicode}```フラグを使う

```js:JS
const ringo = "これは🍎です"
console.log(ringo.length); // 7

const codePoints = Array.from(ringo);
console.log(codePoints); // ['こ', 'れ', 'は', '🍎', 'で', 'す']
console.log(codePoints.length); // 2
```
文字数(code point数)がlengthで出力

```js:JS
console.log("\u{1F34E}"); // => "🍎"
```
正規表現はデフォルトで**code unit**単位で処理される。
code pointでmatchなどさせるなら```\u```でUnicodeであることを示す。

----

## ラッパーオブジェクト

- プリミティブ値の**プロパティ**や**メソッド**にアクセスすると自動で生成されるオブジェクト


以下は明示的に生成しているが、
自動で作成され参照後破棄されている。
```js:JS
// testStrはプリミティブだが、メソッドが呼べる
const testStr = new String("input Value");
console.log(testStr.toUpperCase()); // INPUT VALUE
```
```js:JS
// 自動でラッパーオブジェクトに変換される
const testStr = "input Value";
console.log(testStr.toUpperCase()); // INPUT VALUE
```



### プロパティとメソッドって違うん？
プロパティ≒データとメソッドのこと
データの方を**データプロパティ**という(```.length```とか)

| 動作           | 例                | 説明                                         |
|----------------|-------------------|---------------------------------------------|
| プロパティアクセス | `str.length`      | ラッパーオブジェクトのプロパティにアクセスする。   |
| メソッドの呼び出し | `str.toUpperCase()` | ラッパーオブジェクトのプロパティ（関数）を実行する。 |


### ラッパーオブジェクトを持つ型
- ```null```と```undefined```以外のプリミティブ

| ラッパーオブジェクト | プリミティブ型 | 例                   |
|--------------------|--------------|----------------------|
| Boolean           | 真偽値         | `true`や`false`       |
| Number            | 数値           | `1`や`2`             |
| BigInt            | BigInt       | `1n`や`2n`           |
| String            | 文字列         | `"文字列"`            |
| Symbol            | シンボル       | `Symbol("説明")`      |

## スコープ
- スコープとは**変数**や**関数**が**アクセス可能な範囲**
- スコープ内の変数や関数は**他スコープからアクセスできない**

### 関数スコープ
- 関数内の仮引数やローカル変数はその関数内でのみ使える

```js:JS
function testFunc(x) {
  console.log(x);
}
testFunc("hello"); // "hello"
console.log(x); // x is not defined
```

### ブロックスコープ

- ブロック **```{}```** で囲まれたスコープ
- ```if```や```for```などで使われているのと同じ

```js:JS
{ // ブロックスコープ
  let blockStr = "abc";
}
console.log(blockStr); // blockStr is not defined
```
※```for of```文などはループ毎にスコープを作成する

### スコープチェーン
- ネストされたスコープで変数や関数を参照する際
- **内側=>外側**に向かってたどる仕組みのこと
- 内側を*INNER*, 外側を*OUTER*と呼ぶ場合アリ

```js:JS
{
    // OUTERブロックスコープ
    {
        // INNERブロックスコープ
    }
}
```


内側のスコープから外側の変数や関数は
**参照できる**
外側から内側は**参照できない**

### グローバルスコープ
- どのブロックからも参照できる**一番外のスコープ**
- ここに変数を定義すると**グローバル変数**となる

```js:JS
const globalVariable = "グローバル変数"
// ビルドインオブジェクトもグローバル
Array;
isNaN;
```

#### !変数の隠蔽に注意

- **内側のスコープ**で**外側の変数名を定義**すること
- => 意味が**上書き**されるので先の定義を参照できなくなる

関数などを活用して小さなスコープでプログラムを書く事が重要。


----

### ```var``` ```function```の変数巻上げ
- ```var```や```function```は
- 定義の前に参照できる**巻上げ**が起こる
- ※Hoisting(ホイスト)と呼ばれる

#### ```var```の巻き上げ
- varは**宣言より手前で参照できてしまう**
- スコープも無視され、最も近い**関数スコープの先頭に宣言されたような挙動**がおこる
```js:JS
// var num; ←ここに巻き上げ
console.log(varNum); // undefined
{
  var varNum = 123;
  console.log(varNum); // 123
}
 ```
 **避け方**
 ```var```を使わず```let```を利用する
 ```js:JS
 console.log(varNum); // varNum is not defined
// reference Errorとなり分かる
{
  let varNum = 123;
  console.log(varNum); // 123
}
```

### 関数```function()```の巻き上げ
- 関数宣言より先に**呼び出せる**挙動
- 関数そのものが先頭に移動したような形になる
- ※```var```の巻き上げに比べ悪影響は少ない

```js:JS
hello(); // => "Hello"

function hello(){
    return "Hello";
}
```

※ただし```var hello = ()=> {}```のような**関数式**は```var```の巻き上げを食らうので注意


## 即時実行関数(IIFE)
- **グローバルスコープを汚さないため**の関数の書き方
- 初期化処理などにも使う
- ```var```でも書けるが、昨今は```{}```や```const, let```を使って書く
```js:JS
(function() {
    // 関数のスコープ内でfoo変数を宣言している
    var foo = "foo";
    console.log(foo); // => "foo"
})();
```


 #### 即時実行関数(IIFE)の書き方
 - ```(無名関数{})();```で即時実行される

```js:JS
(function() {
  // 関数の内容
})();
```
**constを使った例**
```js:JS
(function() {
    const foo = "foo";
    console.log(foo); // => "foo"
})();
```

この場合、グローバルスコープを汚さない目的なら以下の様に**ブロック**を使えばよい
```js:JS
{
// 上の即時実行関数と同じ処理
    const foo = "foo";
    console.log(foo); // => "foo"
}
```


### クロージャ
- 関数が外スコープの変数を参照している限り、**その変数の値を覚えている**仕組み
 - => 関数内の変数に**状態**を作り出せる

#### クロージャの書き方
1. 関数を定義
1. 関数内に```状態保持の変数```を作成
1. **return**```状態保持の変数```を操作する関数

```js:JS
function createCounter() {
  // クロージャの保持対象は'count'変数
  let count = 0;

  // createCounterはincrement関数を返す
  return function increment () {
    count = count + 1;
    console.log(count);
  };
}

// 呼び出しは新たな変数に代入し()で処理を呼ぶ
const counter1 = createCounter();
console.log(counter1) // ƒ increment () 

counter1(); // 1
counter1(); // 2
```


https://zenn.dev/ryu0947/articles/109e6dd29bf7f2

https://zenn.dev/takiko/articles/5400a6b0c6bd7d

#### プロパティVSクロージャ
```状態はオブジェクトとプロパティでいいのでは？```

➢プロパティは**外部から参照・操作できる**

変数の状態を**隠蔽したい**時は
**クロージャ**を利用する


- クロージャの例
```js:JS
function createCounter() {
  let count = 0;  // この変数は外部からアクセスできない
  return function() {  
    count++; 
    console.log(count);
  };
}

const counter = createCounter();
counter(); // 1
```
- オブジェクト&プロパティの例
```js:JS
const counter = {
  count: 0,  // countプロパティを作成
  increment: function() {
    this.count++;  
    console.log(this.count);
  }
};

counter.increment(); // 1

// countは外部から直接アクセスできる
console.log(counter.count);  // 3
```
----
## this キーワード
- ```this```は**呼出し方によって意味が変わる**キーワード
- ある時は**オブジェクト**、又ある時は**プロパティ**、**undefined**など...
- コードの簡略化やオブジェクトの関係を簡潔に表すために使う

### strict modeのthis

- 通常、トップレベルに書かれた```this```は```**グローバルオブジェクト**を指す
    - ブラウザ：```Window```
    - node.js：```Global```


```js:JS
// ブラウザ
console.log(this); // => Window
// node
console.log(this); // => Global
```
実行コンテキスト(※環境)によって示すオブジェクトが変わるので**バグ**の原因になる

#### strict modeなら```this```= undefined

- strict modeでは```this```は```undefined```が返される
- **モジュール**は**strict modeが常に有効**。よって```this```は```undefined```になる

```html:HTML
<script type="module">
// 実行コンテキストは"Module"
console.log(this); // => undefined
</script>
```

### 関数とメソッドにおける```this```
- 関数とメソッドにおいては**Arrow Function**と**通常の関数**で挙動が違う
- ```通常の関数```：呼び出し時に決定
- ```ArrowFanction```：定義した時に決定


#### メソッド呼出し(通常の関数)
- メソッドは何らかのオブジェクトに属する
- ```this```は呼出し時に決まる

```js:JS
const person = {
    fullName: "Brendan Eich",
    
    sayName: function() { 
        return this.fullName; // `person.fullName`と書いているのと同じ
    }
};

console.log(person.sayName()); // "Brendan Eich"
```

上記例では、```this```は
ベースオブジェクト(```person```)を示す文言になる

###### ※ベースオブジェクトとは
- ```オブジェクト.メソッド()```
- ```オブジェクト.データプロパティ```
- として呼ぶ際の**左の```オブジェクト.```の部分**

#### 呼出し時に```this```が決まる弊害

通常関数の```this```は**呼出し時に参照元が決まる**から、**問題**が起こる

- メソッドを外部の変数に代入して実行したとき
    - ```オブジェクト```のスコープ外なので```this```が行方不明になる(```global```を指しちゃう)
```js:JS
const person = {
    fullName: "Brendan Eich",

    sayName: function() { 
        return this.fullName; // `person.fullName`と書いているのと同じ
    }
};
// `person.fullName`を出力する
console.log(person.sayName());

const say = person.sayName;
// personのsayNameだけ取出しsayに代入
// `this`はundefinedとなってしまう
console.log(say());
```

#### 対処法
- Functionオブジェクトの専用メソッドで```this```を指定する
    - ```関数.call(thisの対象, 引数...);```
    - ```関数.apply(thisの対象, [引数]);```
    - ```関数.bind(thisの対象, 引数);```
    
      
 ※bindは関数にthisを拘束した新たな関数を作成



```js:JS
"use strict";
function say(message) {
    return `${message} ${this.fullName}！`;
}
const person = {
    fullName: "Brendan Eich"
};
// いずれもthisを明示的に指定するメソッド

console.log(say.call(person, "こんにちは"));
console.log(say.apply(person, ["こんにちは"]));
const sayPerson = say.bind(person, "こんにちは");
// "こんにちは Brendan Eich！"
```

その他、callback関数でthisを使う場合も問題がある

https://k-sugi.sakura.ne.jp/javascript/5363/


### Arrow Functionの```this```
- Arrow Functionでは**1つ外側のthis**を引き継ぐ
- **定義時にこのthisは固定**され文脈により変更されない

```js:JS
const obj = {
  method() {
    const arrowFunction = () => {
    // methodにおけるthis(=obj)を引き継ぐ
      return this;
    };
    // methodはarrowFunction()を返す
    return arrowFunction();
  },
};

console.log(obj.method()); // obj

```
静的なthisの決定を確認
```js:JS
const arrow = obj.method(); 
// functionと違いthisが静的に決定する為、Globalではなくobjが返る
console.log(arrow); // obj
```
----

## クラス

- **クラス**：**動作**や**状態**を定義した構造のこと
- **インスタンス**：**クラスから生成**したオブジェクト
- インスタンスは**クラスに定義した構造を継承する**

### クラスの定義方法(2つ)
- クラス宣言 ```class ClassName{}```
- クラス式 ```variable = class Classname{}```
```js:JS
// クラス宣言文
class MyClass {
  constructor() {
  }
}

// クラス式
const AnonymousClass = MyClass {
    constructor()
}
```
クラス定義では
慣習的に大文字で始まるパスカルケースを使う。```例) MyNewClass ```

----
#### クラス式ではクラス名を省略できる
無名クラスという書き方
```js:JS
const MyClass = class {
  constructor() {
  }
}
```



### ```constructor```関数
**コンストラクタ**とはクラス=>インスタンスを作成する時に、
**インスタンスの状態の初期化**をするメソッドのこと。
- ```constructor(){コンストラクタの処理}```
- (*クラス*を*インスタンス化*したとき**自動的に呼び出される**)

```js:JS
class MyClass {
  constructor() {
  // 初期化に関する処理
  }
}

class MyClass {
  // コンストラクタの省略
}
```

※**コンストラクタ**は処理が無ければ**省略可能**である


### クラスのインスタンス化```new```
- クラスからインスタンス作成することをインスタンス化という
- **```new``` ```class名();```** →でインスタンス化


インスタンスがどのクラス空作成されたかチェックする際は```instansof```：が便利。

```js:JS
// インスタンス化
const myClass = new MyClass();
// 即時でもインスタンス化可能
console.log(new MyClass()); // MyClass {}[[Prototype]]: Object

console.log(myClass instanceof MyClass); // true
```

### 処理のあるコンストラクタの例
以下の例でコンストラクタは
1. インスタンス化時、仮引数```x``` ```y```を受け取る
1. ```this```(生成したコンストラクタ)に**プロパティ**```x``` ```y```を設定する
1. ```x``` ```y```に仮引数値を代入
        

```js:JS
class Point {
  constructor(x, y) {
    // this.x, this.yは
    // インスタンスのプロパティになる
    this.x = x;
    this.y = y;
  }
}

console.log(new Point(1, 2)); // {x: 1, y: 2}
```
**```this```** はコンストラクタにおいて生成したコンストラクタを示す

#### 注意：コンストラクタ関数でオブジェクトを返すのは✖
コンストラクタで```return```した値は```new```した際の返り値になる
➢本来```new```は生成したインスタンスを返すべきなので、好ましくない。
```js:JS
class Square {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    return { x, y }; // 別のオブジェクトを返す
  }
}

console.log(new Square(100, 200)); 
// Squareクラス"ではない"クラス{x: 100, y: 200}
```



### プロトタイプメソッド
- **JavaScriptのクラス**が持つメソッド
- あるクラスから作成されたコンストラクタ間で**参照が共有される**
- (クラスのメソッドは全てこれ)



##### **メソッドの定義**
```メソッド名(){メソッドの処理}```
```js:JS
class Counter {
  constructor() {
  // thisはCounterのインスタンスを示す
    this.count = 0;
  }
  // incrementメソッドを定義
  increment() {
    this.count++;
  }
}
```
##### **メソッドの呼出し**
```コンストラクタ.メソッド(引数)```

```js:JS
const counterA = new Counter();
const counterB = new Counter();

// メソッド呼出し
counterB.increment(); // countプロパティ: 0 -> 1
```
プロパティの参照：```コンストラクタ.プロパティ```

```js:JS
// プロパティ確認
console.log(counterB.count) // 1
```
#### メソッドの共有
CounterAとCounterBでは、
**incrementメソッドは共有されている**

```js:JS
// 以下はtureになる
console.log(CounterA.increment === counterB.increment);
```
この様にプロトタイプオブジェクトの仕組みでは、
同クラスの別インスタンス同士で**メソッドの参照を共有する**

### アクセッサプロパティ```getter``` ```setter```

- クラスのプロパティを参照・代入する際に使う**メソッド** 
    - 参照は ```getter```を使う
    - 代入は ```setter```を使う

(メソッドだが使い方はプロパティチックな為、アクセッサプロパティと呼ぶ)

##### **なぜアクセッサプロパティが必要なのか？**
秘匿性や安全性、利便性にメリットがあるから。

| **目的**            | **説明**                                                 |
|----------------------|---------------------------------------------------------|
| データのカプセル化   | 内部データを隠しつつ安全にアクセス・更新する。           |
| 動的な処理の追加     | 値の取得・設定時にバリデーションや計算を行える。         |
| データの整合性確保   | 不正な値の設定を防ぎ、一貫性を保つ。                     |
| 柔軟なAPI設計       | 外部からの使い方を変えずに内部実装を調整可能。           |

#### 書き方
- コンストラクタ定義後
- ```get プロパティ名(){return 返値}```
    - ※ returnはgetterにおいて必須
- ```set プロパティ名(仮引数){set処理}```
    - ※ 値を返す必要は無い




```js:JS
class NumWrapper {
  constructor(value) {
    return (this._value = value);
  }
  // getter
  get value() {
    return this._value;
  }
  // setter
  set value(newValue) {
    this._value = newValue;
  }
}
```
#### ```get``` ```set```呼び出し
- get
    - ```インスタンス名.プロパティ名```
- set
    - ```インスタンス名.プロパティ名 〇〇処理```

```js:JS
// インスタンス化
const numWrapper = new NumWrapper(10);

// getで表示
console.log(numWrapper.value); // 10

// setで代入
numWrapper.value = 30;
console.log(numWrapper.value); // 30
```
##### 注意：```_```から始まるプロパティ
プロパティには直接参照されたくない場合があり、```_value```の様にする慣習があった
(現在は**```#value**```のような*Private class field*という機能が用意されている)


### クラスフィールド
- インスタンスの持つプロパティを**より簡単に指定**するための構文
- 外部からアクセス出來るクラスフィールドを、**publicクラスフィールド**という

プロパティを```プロパティ = 初期値```と書ける

```js:JS
class MyTestClass {
  // クラスフィールドによるプロパティ
  property1 = "Class Field";
  // コンストラクタによるプロパティ
  constructor(arg) {
    this.property2 = arg;
  }
}

const myNewClass = new MyTestClass(2);
console.log(myNewClass.property1) // "Class Field"
console.log(myNewClass.property2) // 2
```

初期値を省略したプロパティ(クラスフィールド利用。省略で初期値は```undefined```となる)
```js:JS
class Loader {
    loadedContent;
    load() {
        this.loadedContent = "読み込んだコンテンツ内容";
    }
}
```



### クラスフィールドの```this```
クラスフィールドの```this```は**クラスのインスタンス**を示す
```js:JS
class Counter {
    count = 0;
    // thisはCounterインスタンスを示し、
    // upはそのincrementメソッドを参照している
    up = this.increment;
    increment() {
        this.count++;
    }
}
```

**この性質どう使う？**
➢ArrowFunctionと組み合わせて、

関数としてメソッドを実行する際におこる、**thisの呼出し時決定の性質によるエラー**に対処できる

```js:JS
class Counter {
  count = 0;

  increment() {
    // thisはCounterインスタンスを指す
    this.count++;
  }
}

const newCounter = new Counter();

// incrementを変数に代入し、次で呼出す
// thisがスコープを外れundefinedになる
// エラーが発生
const increment = newCounter.increment; 
increment(); // Uncaught TypeError

```
上記はメソッドを関数として呼ぶ際、
```this```がglobalオブジェクトを指してしまう**ことが原因。
(strict modeでは```undefined```)


**対処**
----
**クラスフィールド上でメソッド呼出しをArrowFunctionで定義**すると、thisが固定される
```js:JS
class Counter {
  count = 0;

  // countUpフィールドに関数式
  // thisがインスタンスに固定される
  countUp = ()=> {
    this.increment(); 
  }
  increment() {
    this.count++;
  }
}

const newCounter = new Counter();

const up = newCounter.up; 
up; // 正しくincrement
```

### Privateクラスフィールド
- クラスフィールドを```#field```と記述
- インスタンス化後に**クラス内からのアクセスに限定できる**※プロパティ参照などできない
- ```getter``` ```setter```と併せて使える

```js:JS
class TestClass {
  _value; // フィールド定義
}

const testClass = new TestClass();
console.log(testClass._value); // undefined
```
上記例では```_value```フィールドにアクセスできる


**private化**
```#value```で参照した際構文エラーでアクセス不可にできる

```js:JS
class TestClass {
  #value; // フィールド定義
  constructor() {
    this.#value = undefined;
  }
}

const testClass = new TestClass();
console.log(testClass.#value); // error
```

### 静的メソッド
- クラスを**インスタンス化せず利用できる**メソッド
- クラスメソッドとも呼ぶ
- メソッドの前に```static```をつける

**数値を受けとりインスタンス化する静的メソッド```of```を実装した例**

```js:JS
class ArrayWrapper {
  constructor(array = []) {
    this.array = array;
  }

// ...valueで入力を配列に変換して受け取る(残余引数)
  static of(...items) { 
    return new ArrayWrapper(items); // ArrayWrapperをインスタンス化
  }

  get length() {
    return this.array.length;
  }
}

const ArrayWrapperA = new ArrayWrapper([1, 2, 3]);

// new でインスタンス化せずofメソッドを利用する
// of内でインスタンスを生成
const ArrayWrapperB = ArrayWrapper.of(1, 2, 3);
console.log(ArrayWrapperB.length)
```

また上記```of```の```new ArrayWrapper```は、**this**でも良い

```js:JS
static of(...items){
    return new this(items);
}
```
## 静的クラスフィールド
- **クラス自体(Prototypeオブジェクト)に設定されたフィールド**(プロパティや変数)
- ```static フィールド名```

```js:JS
//  静的クラスフィールド
class Colors {
  static red = "赤";
}

// インスタンス化せずクラスフィールドを呼び出す
console.log(Colors.red) // "赤"
```

また、```#(private)```をつけて外部から秘匿もできる
```js:JS
//  静的クラスフィールド
class Colors {
  static #red = "赤";
}


// 非公開のプロパティにアクセスしているので
// 未定義undefinedが返る
console.log(Colors.red) // undefined
```

### プロトタイプに定義したメソッド、インスタンスに定義したメソッド
- プロトタイプに定義したメソッド
    - **クラスにメソッド構文```method(){}```で定義**
    - プロトタイプオブジェクトとして保存
    - インスタンス間で共有
- インスタンスに定義したメソッド
    - クラスから作成したインスタンス毎に定義されるメソッド
    - **アロー関数```method = ()=> {}```で定義**


### プロトタイプチェーン
- インスタンスに**プロトタイへの参照を記録する**
- インスタンスからプロパティを探す際、**インスタンス➢プロトタイプオブジェクト**まで探索する機能

```js:JS
class MyClass {
    method() {
        console.log("プロトタイプのメソッド");
    }
}
const instance = new MyClass();
// インスタンスには`method`プロパティがないため、プロトタイプオブジェクトの`method`が参照される
instance.method(); // "プロトタイプのメソッド"
// `instance.method`の参照はプロトタイプオブジェクトの`method`と一致する
const Prototype = Object.getPrototypeOf(instance);
console.log(instance.method === Prototype.method); // => true
```

----
- `class1.prototype` と `class2.prototype` は異なるオブジェクトで、個別にメソッドやプロパティを持つ。
- 両者は共通で `Object.prototype` を参照し、`Object.prototype` のメソッドは利用可能。
- クラス間でメソッドやプロパティを共有するには、**継承**を使う必要がある。
- 継承により、サブクラスの `prototype` は親クラスの `prototype` を参照する。
----
https://maeharin.hatenablog.com/entry/20130215/javascript_prototype_chain


## 継承
- **クラスの構造や機能を引き継いだクラスを作ること**
- ```extends```キーワードを使う
。
```extends Parent```で親クラス(継承元)のメソッドを継承し呼び出す例

```js:JS
class Parent {
    name; // プロパティ定義
  hello = (name) => {
    this.name = name; //プロパティに代入
    console.log(`hello, ${this.name}`);
  };
}

class Child extends Parent {
    // Parentのメソッドhelloを継承
}

const childClass = new Child;
// 変数として呼出し
const x = childClass.hello;
x("wawawa"); // hello, wawawa
```
### ```super()``` 親クラスのコンストラクタを継承
- 単純な継承のみなら、**自動でコンストラクタ・メソッド**は勝手に継承される
- ```super()```を使う場合↓
    - 子クラスで独自のコンストラクタを定義する
    - メソッドを**オーバーライド**する

```js:JS
class Parent {
  constructor(...args) {
    console.log("constructor1:" + args);
  }
}

// ---Parentコンストラクタを引き継いだ上
// ---独自に処理を追加する
class Child extends Parent {
  constructor(...args) {
    // 親クラスにもargsを引き継ぐ
    super(...args);
    console.log("constructor2:" + args);
  }
}

const child = new Child(1,2); 
// constructor1:1,2
// constructor2:1,2
```
```super()```をつけないで新たなコンストラクタを定義すると**エラーになる**
```js:JS
class Child extends Parent {
  constructor(...args) {
    console.log("child constructor:" + args);
  }
}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/e18c0e1d-f70c-cad1-0a0d-d6e43b48f62c.png)

---- 
### クラスフィールド(プロパティ)の継承
- クラスのフィールドもインスタンスに継承される
- この場合**インスタンスの**フィールドとして定義される


※親クラスで```private```なフィールドは継承先でも```private```となる

```js:JS
class Parent {
  field = "field.";
  #privateField = "private field.";
}

class Child extends Parent {
  // フィールドは両方継承
  showPrivate(){
    console.log(this.#privateField);
  }
}

const child = new Child();
console.log(child.field); // "field."
child.showPrivate; // SyntaxError: Private field
```

※そもそも**フィールド**と**メソッド**は異なる
- **フィールド**：クラスにおけるプロパティ。**状態を保持するためのもの**
- **メソッド**：クラスやオブジェクトにおける**振る舞いを定義するもの**
----
#### 継承＝すべてを複製”ではない！”
- メソッドは親クラスのものを再利用(参照)する(メソッドチェーン) 
- フィールドは**コンストラクタに複製されたもの**を参照する


| 特徴                          | フィールド                                      | メソッド                                    |
|-------------------------------|-------------------------------------------------|---------------------------------------------|
| **役割**                       | インスタンスの状態を保持するプロパティ           | インスタンスの動作を定義する関数             |
| **格納される場所**             | インスタンスごとに格納される                     | プロトタイプチェーンを通じて共有される       |
| **インスタンスごとの独立性**   | インスタンスごとに独立した値を持つ               | すべてのインスタンスで共有される             |


### ```super```プロパティ
- 子クラスのプロトタイプメソッドから親クラスのプロトタイプメソッドを呼び出す

```js:JS
class Parent {
    method() {
        console.log("Parent.prototype.method");
    }
}
class Child extends Parent {
    method() {
        console.log("Child.prototype.method");
        // `this.method()`だと自分(`this`)のmethodを呼び出して無限ループする
        // そのため明示的に`super.method()`を呼ぶことで、Parent.prototype.methodを呼び出す
        super.method();
    }
}
```


## matome:クラスとプロトタイプとインスタンスの関係

- **クラス**
    - 構造の設計図のようなもの
    - 値と振る舞いを定義されている
- **プロトタイプオブジェクト**
    - インスタンス間で共通するデータやメソッドを持つオブジェクト
    - "クラス"を定義した段階で自動作成される
- **インスタンス**
    - クラスからできた実体
    - 独自のメソッドやフィールドを持てるし、プロトタイプのデータやメソッドを参照し利用したりもできる


----
## 例外処理 ```try...catch```
例外発生時の特別な処理をする
- **```try{対象} cach(error){エラー時の処理}```**
- ```finaly{}```
    - errorに関係なく必ず```try```節の後に実行される処理

```js:JS
try {
  console.log("step1"); // step1
  // error原因の処理
  undefinedFunction();

  // error以降は実行されない
  console.log("step2");
} catch (error) {
  console.log(error.message); // undefinedFunction is not defined
} finally {
  console.log("step3"); // step3
}
```

### ```throw``` エラーオブジェクトを投げる
- ```throw new Error()```でエラーを明示的にで投げる(Errorは他の基本的なエラーも使える)
- 
- ```catch```節でエラーを受け取り
```js:JS
try {
  // catchのerror変数に投げたエラーが格納される
  throw new Error("例外が投げられました");
} catch (error) {
  console.log(error.message); // "例外が投げられました"
}
```
```Error()```の部分は他の種類のエラーも用いる場合がある
- Errorオブジェクト
    - ```Error``` : あらゆるエラー
    - ```Reference Error``` : 存在しない参照へのアクセス
    - ```Syntax Error``` : 存在しない構文
    - ```Type Error``` : 型が期待と異なる

Reference Errorの例
```js:JS
// reference error
try {
  console.log(x);
} catch (error) {
    console.log(error instanceof ReferenceError); // true
    console.log(error.name) // "Reference Error"
    console.log(error.massage) // "エラーメッセージ"
}
```
これらの内臓されたエラーを**ビルドインエラー**という

### ```console.error
- ```console.error()```でスタックトレースを表示できる。console.logよりデバッグに有利
- ※スタックトレース：エラーの詳細を追跡したログ

```js:JS
function fn() {
    console.log("メッセージ");
    console.error("エラーメッセージ");
}

fn();
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/d72efa2f-5349-9b98-dbf4-33775801c141.png)

----
## 非同期処理
- **非同期的なタイミングで実行される**処理
- ⇔同期処理。タスクの順番通り処理する
- メインスレッドで実行される

### ```setTimeout()```
- 指定した時間経過後に**コールバック関数**を実行する
- ```setTimeout(()=> {callBack}, ミリ秒);```
    - ※一般的にはArrowFanction形式で引数渡す

```js:JS
setTimeout(()=> {
    console.log("5秒後に表示");    
}, 5000);
```
非同期によって、処理の完了を待たず次を実行できる

```js:JS
setTimeout(() => {
  console.log("task B");
}, 5000);

console.log("task C");
// task A
// task C
// task B
```

### 非同期の例外処理
- 非同期処理で発生したエラーは```try...catch```で捕捉できない。

```js:JS
try {
    setTimeout(() => {
throw new Error()
      }, 5000);
} catch (error) {
    // エラー時処理はスルー
        console.log("エラーが発生しました")
}
// try内を実行後に非同期処理
// エラーが5秒後に発生。
```

↓catchの内容はスキップされる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/ab38acb8-2325-8024-6ab3-0dfffc8580b5.png)


このエラーをキャッチするのであれば以下の様に、```setTimeout```内で```try...catch```する

```js:JS
setTimeout(() => {
  try {
    throw new Error();
  } catch (error) {
    console.log("エラーが発生しました");
  }
}, 5000);
```

### Promeiseオブジェクト

- 関数内などで
    - ```return new Promise(resolve, reject) =>{ 非同期処理したい内容 }``` 

- 関数を実行時に
    - ```関数名().then(()=>{A}).catch((B)=>{})```
    - Aには成功時にしたい処理
    - Bには失敗時にしたい処理

例：ランダムに処理が成功・失敗するコード
```js:JS
function fetchData() {
    return new Promise((resolve, reject) => {
      const isSuccess = Math.random() > 0.5; // 成功するか失敗するかをランダムに決める
  
      setTimeout(() => {
        if (isSuccess) {
          resolve("データの取得に成功しました！"); // 成功時
        } else {
          reject("データの取得に失敗しました..."); // 失敗時
        }
      }, 2000); // 2秒後に結果を返す（非同期処理のシミュレーション）
    });
  }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/d03fbdcc-8e05-46e7-703e-ee7746126d41.png)


基本的な書き方は以下
```js:JS
function asyncFunc() {
  return new Promise((resolve, reject) => {
    // 非同期でしたい処理
    // なんらかの結果がでる
    if (成功条件) {
      resolve(); // これが実行されると成功
    } else {
      reject(); //これが実行されると失敗
    }
  });
}

// 呼出し
asyncFunc()
  .then(() => {
    成功時の処理;
  })
  .catch(() => {
    失敗時の処理;
  });

```

Promiseオブジェクトは```resolve()```か```reject()```の実行で状態が変化。
実行中・成功・失敗の状態を表す。
- ```resolve()```関数が実行されると成功(**Fulfilled**)状態
- ```reject()```関数が実行されると失敗(**Rejected**)状態
- 成功も失敗もまだない(保留中)(**Pending**)状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230965/033ca0b5-84de-7504-9ac3-64960cefbc43.png)


### Promiseチェーン

- Promiseによる非同期処理を**メソッドチェーン**で繋ぐこと
- 連続で非同期処理を実行できる

```js:JS
Promise.resolve()
  // promiseインスタンスが返る
  .then(() => {
    console.log("成功1");
  })
  .then(() => {
    console.log("成功2");
  })
  .then(() => {
    console.log("成功3");
  })
// 成功1
// 成功2
// 成功3
```
ちなみに失敗が間に挟まると、処理を書かない限り**catch処理成功**とし、続くthenは実行される。
```js:JS
Promise.reject()
  // promiseインスタンスが返る
  .then(() => {
    console.log("成功1");
  })
  .then(() => {
    console.log("成功2");
  })
  .catch(()=>{
    console.log("失敗！")
  })
  .then(() => {
    console.log("成功3");
  })
// 1, 2はスキップ
// 失敗！
// 成功3
```


例)ユーザ情報を得るために、メソッドチェーンを利用する
```js:JS
// サーバーからユーザー情報を取得する関数
function getUserInfo(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const user = { id: userId, name: "Taro", age: 25 }; // ダミーデータ
      resolve(user); // 成功時、ユーザー情報を返す
    }, 1000); // 1秒後にユーザー情報を返す
  });
}

// ユーザーのプロフィールを更新する関数
function updateProfile(user) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      user.name = "Taro Yamada"; // 名前を変更
      resolve(user); // 更新後の情報を返す
    }, 1000); // 1秒後に更新された情報を返す
  });
}

// 実行例
getUserInfo(1)
  .then((user) => {
    console.log("ユーザー情報:", user); // ユーザー情報を表示
    return updateProfile(user); // ユーザー情報を使ってプロフィールを更新
  })
  .then((updatedUser) => {
    console.log("更新後のユーザー情報:", updatedUser); // 更新後の情報を表示
  })
  .catch((error) => {
    console.error("エラー:", error); // エラーがあれば表示
  });
```