第 2 章 エッジでディープな JavaScript の世界 メモ

TypeScript は JavaScript に静的型付けによる拡張された型システムを加えた上位互換の言語
JavaScript を学ぶ上で、C の系譜にある言語という先入観はむしろ障害になると思う
ECMAScript は Ecma International67 という業界団体が定めている JavaScriptの標準仕様

###var / const / let
変数の宣言には var キーワードを使っていたのかもしれないけど、これはもう金輪際、使ってはいけません
今の JavaScript には const と let という変数を宣言するためのキーワードが追加されてる。だからその 2 つを代わりに使う
従来からある var は、安全なプログラミングをする上で次のような問題を抱えてる
1. 再宣言および再代入が可能
2. 変数の参照が巻き上げられる
3. スコープ単位が関数

var は再宣言も再代入も可、let は再代入のみ可、const はどちらも不可
var で定義された変数のスコープって関数単位なんだよ。だから制御構文のブロックをすり抜けてしまう。

あくまで const が第一選択肢で、どうしても再代入が必要なときだけ let

###型
静的型付け言語は変数 や、関数の引数および戻り値の型がプログラムの実行前にあらかじめ決まってなければいけないの に対して、動的型付け言語ではそれらが実行時の値によって文字通り動的に変化する

データ型が『プリミティブ型』と『オブジェクト型』の 2 つに大別される

値がプリミティブであるというのは、それがオブジェクトではない、インスタンスメソッドを持たないデータだということ。
JavaScript のプリミティブ型は今のところ次の 7 種類がある
・Boolean 型…… true および false の 2 つの真偽値を扱うデータ型。
・Number 型…… 数値を扱うためのデータ型。他の多くの言語と異なり、整数も小数も同じ Number 型になる。扱うことができる最大値は 253-1（9,007,199,254,740,991 ≒ 9 千兆）。
・BigInt 型…… Number 型では扱いきれない大きな数値を扱うためのデータ型。ES2020 で追加された。Number 型と互換性がなく、相互に代入や計算、等値比較などは行えない。
・String 型…… 文字列（テキストを表す連続した文字）を扱うためのデータ型。
・Symbol 型……「シンボル値」という固有の識別子を表現する値。ES2015 から導入された。Symbol() 関数を呼びだすことで動的に生成されるが、基本的に同じシンボル値を後から作成できない。オブジェクトのプロパティキーとして使用可能。
・Null 型…… プリミティブ値 null は何のデータも存在しない状態を明示的に表す。・Undefined 型…… プリミティブ値 undefined は宣言のみが行われた変数や、オブジェクト内の存在しないプロパティへのアクセスに割り当てられる。他の多くの言語と異なり、null と明確に区別される。
・Undefined 型…… プリミティブ値 undefined は宣言のみが行われた変数や、オブジェクト内の存在しないプロパティへのアクセスに割り当てられる。他の多くの言語と異なり、null と明確に区別される。

プリミティブ型の値を定義するのには、通常『リテラル（Literal）』を使う。『literal』とは『文字通り』という意味の単語で、プログラミング言語においてはソースコードに数値や文字列をベタ書きしてその値を表現する式であることからこう呼ばれる

各プリミティブ型に用意されてるリテラル
・Boolean 型…… true と false の 2 つの真偽値リテラルがある。
・Number 型…… 36 や -9 のように数字を記述する数値リテラル。先頭に 0x をつけることで 16 進数、0o をつけることで 8 進数、0b をつけることで 2 進数が表現される。他に 3.14 や 2.1e8 などの形式で表現する浮動小数点リテラルがある。
・BigInt 型…… 100n のように数字の後ろに n をつけて表現する数値リテラル。
・String 型…… シングルクォート ' またはダブルクォート " で囲む文字列リテラル。バッククォート `を用いると、改行を含む複数行テキストや ${} による式の展開が可能なテンプレートリテラルになる。
・Null 型…… null リテラル である null は、プリミティブ値 null を返す。
null と undefined を除くすべてのプリミティブ型には、それらの値を抱合する『ラッパーオブジェクト（Wrapper Object）』というものが存在してる。
JavaScript では必要に応じてプリミティブ値が自動的にオブジェクトに変換されるので、わざわざラッパーオブジェクトのインスタンスを生成する必要はない

###オブジェクト型とそのリテラル
・配列リテラル…… [1, 2, 3] の形式で記述する。[] は空の配列を示す。arr[n] という構文で n-1 番めの要素にアクセスできる。Array オブジェクト 78 のインスタンスとして生成される

・オブジェクトリテラル
{ key: value } の形式で記述する。{} は空のオブジェクトを示す。任意のプロパティ値にアクセスするには obj[key] または obj.key の 2 つの構文が利用できる。Object オブジェクト 79 のインスタンスとして生成される。

・正規表現リテラル…… /pattern/frags の形式で記述する。正規表現パターンでの特殊文字の使い方は、他の言語とほぼ共通 80。RegExp オブジェクト 81 のインスタンスとして生成される。
JavaScript でいう『オブジェクト』とは通常、キーとそれに対応する値を持ったプロパティの集まりであり、一般的には『連想配列』と呼ばれる
オブジェクトはさかのぼるとすべて組み込みオブジェクトの Object がベースになってる
JavaScript では、関数は文でも式でもどちらによっても定義できる
プログラミングにおける『文（Statement）』というのは何らかの手続きを処理系に命令するもの。いっぽう『式（Expression）』は評価された後に値として存在するもの。簡単にいえば変数に代入できるのが式、できないのが文

```javascript
//関数宣言文による定義
function double(n) {return n * 2;}

// 関数式による定義
const twice = function (n) {return n * 2;};
```
JavaScript では文の末尾にはセミコロンが必要、{} のブロックで終わる場合にはつけないという例外規則がある、逆に関数式のほうは最終的に変数への代入文になってるから、末尾にセミコロンを付ける必要がある

const を使った関数式のほうを推奨
なぜかというと、再宣言ができてしまうことと、宣言の巻き上げがある
JavaScript では関数は組み込みオブジェクト Function のインスタンスであり、『第一級オブジェクト（First-Class Object）』でもある
他のオブジェクト型の値と同様に、変数へ代入したり、配列の要素やオブジェクトのプロパティ値にしたり、他の関数に引数として渡したり、別の関数の戻り値として設定できたりする

関数は第一級オブジェクト、そうであるがゆえにオブジェクトのプロパティ値にも設定できる。そして JavaScript においては、単にオブジェクトのプロパティとなってる関数のことを『メソッド』と呼ぶ

###アロー関数
アロー関数式

```javascript
const addOne = (n) => {return n + 1;};
```

アロー関数式、さらに省略記法

```javascript
const increment = n => n + 1;
```

```javascript
function addTwo(n) {
  return n + 2;
}
```
アロー関数式では引数がひとつだけの場合はカッコが省略できる、本文が return 文だけのときは、return 文をブロックごと省略できる

```javascript
> function mercury() {}
> mercury.name // 宣言文で定義した関数の名前'mercury'
> const fn = function mars() {};
> fn.name // 関数式で定義した関数の名前'mars'
```
関数の名前は Function インスタンスとしての name プロパティに格納されてる。

無名関数

```javascript
> (function () {}).name
''
> (() => {}).name
''
```

無名関数を変数に代入すると、変数名が関数名になる

```javascript
> const jupiter = () => { console.log('I am Jupiter!'); };
> jupiter();I am Jupiter!
> jupiter.name
'jupiter'
```

デフォルト引数

```javascript
const raise = (n, m = 2) => n ** m;
console.log(raise(2, 3)); // 8 
console.log(raise(3)); // 9
```

レストパラメータ
引数の名前に ... のプレフィックスを付けることで『残り』の引数を配列として受け取ることができる

```javascript
const showNames = (a, b, ...rest) => {
console.log(a);
console.log(b);
console.log(rest);
};
showNames('John', 'Jane', 'Johnny', 'Jenny', 'Julia');
// John
// Jane
// [ 'Johnny', 'Jenny', 'Julia' ]
```

第 1 引数としてレストパラメータを設定すれば、引数の中身を全部持ってこれる

```javascript
const showAllArgs = (...args) => {
console.log(args);
};
console.log(showAllArgs('A','B','C','D')); //['A','B','C','D']
```

分割代入

```javascript
const [n, m] = [1, 4]; console.log(n, m); // 1 4
const obj = { name: ‘Kanae’, age: 24 }; const { name, age } = obj;
console.log(name, age); // Kanae 24
```

スプレッド構文

```javascript
const arr1 = [‘A’, ‘B’, ‘C’];
const arr2 = [...arr1, ‘D’, ‘E’];
console.log(arr2); // [ ‘A’, ‘B’, ‘C’, ‘D’, ‘E’ ]
constobj1={a:1,b:2,c:3,d:4}; 
const obj2 = { ...obj1, d: 99, e: 5 };
console.log(obj2); //{a:1,b:2,c:3,d:99,e:5}
```
レストパラメータ構文と配列のスプレッド構文は、本質的には同じ

###ショートサーキット評価
OR 演算子 || は左辺が falsy な値だと評価が右辺に渡 される。
AND 演算子 && を使ってるので逆 に左辺が truthy な値のときに評価が右辺に渡される

```javascript
const hello = undefined || null || 0 || NaN || ‘’ || ‘Hello!‘;
const chao=‘’&&100&&[]&&{}&&‘Chao!’;
true&&console.log(‘1.’,hello); //1.Hello!
false&&console.log(‘2.‘,hello); //(nooutput)
true || console.log(‘3.’, chao); // (no output)
false||console.log(‘4.’,chao); //4.Chao!

const user = await repo.getUser();
const userName = user?.name || "不明なユーザー";
const userName = user ? user.name : "不明なユーザー";

if (isMute && isConnected)
const isReady = isMute && isConnected;
```
?? を並べてる部分が Nullish Coalescing、?. でつないでる部分が Optional Chaining
?. 演算子を使うと、チェーン内の各参照が正しいかどうかを明示的に確認せずにアクセスしていくことができる。途中のプロパティが存在していなかったら、そこで式が短絡 されて undefined を返してくれる

###JavaScript の this とは何なのか
this とは、その関数が実行されるコンテキストであるオブジェクトへの 参照が格納されている『暗黙の引数』
(1)new 演算子をつけて呼び出したとき: 新規生成されるオブジェクト
(2)メソッドとして実行されたとき: その所属するオブジェクト
(3)1・2 以外の関数[非 Strict モード]: グローバルオブジェクト
JavaScript におけるトップレベルの実行環境は必ず何らかのグローバルオブジェクトになってる。
メソッドではない関数、および new 演算子をつけずに実行されるあらゆる関数は、このグ ローバルオブジェクトが this として引き渡される
・this はクラス構文内でしか使わない
・クラス構文内では、メソッドを含めたあらゆる関数の定義をアロー関数式で行う

###現在のモジュールバンドラ(webpack)がやってくれてる仕事
・Minify ...... 空白文字やコメント、実行されないコードやコンソール出力などを削除、変数名や 関数名を短縮、条件文や宣言文を簡略化するなどして、スクリプトファイルの容量を最小限に圧 縮する
・Tree Shaking ...... どこからも参照されていないモジュールを検出してバンドル対象から外し、 出力ファイルの容量を削減する
・画像データのインライン埋め込み ...... 画像ファイルを『データ URL134』としてドキュメントに インラインで埋め込む(※ CRA のデフォルト設定では 10KB 以下の画像ファイルはデータ URL 化される 135)
・コード分割 ...... モジュールの共有度合による自動分割に加え、開発者がアプリケーションの UI や規模を考慮しつつ、バンドルファイルを適切な粒度に分割し、それぞれが適切なタイミン グで読み込まれるようにできる
・キャッシュ管理 ...... ビルド時に出力ファイルの名前に差分単位でユニークな ID を付与するこ とで、ブラウザキャッシュが適切に使われるようにし、かつキャッシュが残ることによる挙動の 不具合を予防する他にもBabel で ES5 にコンパイルなど

###名前付きエクスポート(Named Export)とデフォルトエクスポート(Default Export)　がある
デフォルトエクスポートができるのは、1 モジュール(= 1 ファイル)につき 1 回まで
モジュール間で名前がバッティングしてしまうときや、長い名前を省略して取り回したいとき とかに、as キーワードを使うことで名前を変更できる

###参考書籍
https://oukayuka.booth.pm/items/2368045