JavaScriptのメカニズム（変数）

# 参考
[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence)

# あらすじ
現場でrailsを触ってlaravelを触って今はtypescriptとreact-routerで実装することが多くなってきたが、今までJavascriptをがっつり勉強してなかったので復習も兼ねて上記講座を受けてみようと思った。

とある先輩から「エンジニアじゃない人間が聞いてもわかる程度の説明にしろ」という言葉をいただいたので、できるだけ頑張る。

# 変数とは
値（データ）を受け取る箱
JSでは`var`,`let`,`const`がある。
- var
関数スコープ。再宣言、再代入が可能。
- let 
ブロックスコープ。再代入が可能。
- const
ブロックスコープ。再宣言、再代入不可能。

```javascript
//再宣言
var hoge = a;
var hoge = b; //これは可能

//再代入
let hoge= a;
a = fuga; //これは可能
```

また、`var`は関数スコープのため、変数宣言は巻き上げが可能となる。
```javascript
function fn(){
    console.log(makiage); // undefinedと出力される
    var makiage = '巻き上げなう';
}

fn();

// 内部的には以下のように解釈される
// var makiage;           // 宣言が巻き上げられる
// console.log(x);  // undefined
// makiage = '巻き上げなう';          // 代入はそのままの位置
```

巻き上げができない例
```javascript
function fn(makiage){
    console.log(makiage);
    const makiage = '巻き上げなう';
}

fn();

// fn内で宣言している変数をconstで再代入しているためNG
```

# 主なデータ型
JSで主に以下のデータ型がある。
|型|英名|例|
|:--:|:--:|:--:|
|真偽値|Boolean|true/false|
|数値|Number|12|
|文字列|String|"Hello"|
|undefined|undefined|undefined|
|null|Null|null|
|シンボル|symbol|一意の意味|
|BigInt|BogInt|12n|
|オブジェクト|Object|{a: value}|

個人的には数値をintと勘違いするので気をつけたい。

※undefinedとnullの違い
null = トイレットペーパーの芯だけの状態
undefined = そもそもトイレットペーパーがセットされてない

# 暗黙的な型変換
JavaScriptは暗黙的に型変換を行なってしまう。
暗黙的な型変換は片方が優先される。

```javascript
function printTypeAndValue(val) {
    console.log(typeof val, val);
}

let a = 0;
printTypeAndValue(a);
// Number 0

let b = '1' + a;
printTypeAndValue(b);
// '10'
// 最初が文字列なので文字列結合として扱われる

let e = 5 - true;
printTypeAndValue(e);

// これは5がint、trueがbooleanだが、booleanでのtrueは1、falseは0なので
// intに置き換えられて4と出力される
```

# 厳格な等価性と抽象的な等価性
イコールの形で評価が変わる。
イコール一つは代入なのでここでは説明なし。
`===`なら型も含めて評価する
`==`なら見た目で評価する。
手間暇かけた方が厳格に判断できるってこと。

```javascript
// 厳格：
a===b //（型比較あり）

// 抽象：
a==b //（型比較なし）
```

# falselyとtruthly
falslyな値＝booleanで真偽値に変換した場合、falseになる値
fanselyの例: `false,null,undefined,0,NaN,a`

値が入っているかどうかはいろんなとこで使うので
以下のイディオムは覚えておくのが吉。
以下は値が入っていれば処理を行う。
```javascript
if (hoge){
    // 処理
}
```

逆に以下の場合は値が入っていなければ処理を行う
```javascript
if (!hoge){
    // 処理
}
```
ただし上記の場合、値が整数`0`の時もfalseに分類されるので注意。

# AND条件とOR条件
`&&` -> AかつB
`||` -> AまたはB

ここで気をつけたいのが
`&&はfalseがあればその時点で評価が終わる`
`||はtrueがあればその時点で評価が終わる`
```javascript
a = 1;
b = 0;
c = 3;

console.log(a && b && c);
// 0が出力される

console.log(a || b || c);
// 1が出力される
```

よく使う例

```javascript
name = name || 'tom';
// nameがあればname、false（null等）は'tom'とする

name = name ? 'taro' : 'tom';
// nameがあれば'taro'、false（null等）は'tom'とする
```

# プリミティブ型とオブジェクト
- プリミティブ型
オブジェクト型以外のものをプリミティブ型という。immutable(不変)の性質を持ち、変数には値が入る。一度作成したらその値は更新できない。
ここでいう更新できないのは以下のように
```javascript
let a = 'Hello';
a = 'Bye';
```
のようにしても`let a = 'Hello'`はメモリ上に残るということ。

- オブジェクト
変数には参照が格納される。値を変換できる。
オブジェクトとは、名前付きの参照を管理する入れ物。

# 参照
オブジェクトで使う考え方
```javascript
let c = {
    prop: 'hello'
}
let d = c;
d.prop = 'bye';
console.log(c, d);
// これはどっちもbyeが入る
```
オブジェクトに関して、値は変更できないが、プロパティは変更できる。

```javascript
let c = {
  prop: 'hello'
}
let d = c;
// d.prop = 'bye';
d = {};
console.log(c, d);

// これはhelloと{}が返る
```

constの場合**ロック**がキーワードで、参照行為がロックされる。
だからconstは上書き（再代入）できない。
プリミティブの場合、値への参照がロックされる。
```javascript
const a = 'hello';
a = 'bye'; 

// aの値の参照は`hello`でその参照がロックされている。
// a = 'bye'の参照の貼り直しができない。
```

オブジェクトの場合、constはaのオブジェクトの参照をロックしている。
```javascript
const a = {
    prop: 5
}

a = {} 
//これはNG。
//aの参照は{}（オブジェクト）でそれがロックされているため、オブジェクトの参照を貼り直すことができない。

a.prop = 10; //これはOK
```
これはオブジェクトのa->{}(ブロックの中身)->prop->5の道筋の中でa->{}の部分の参照がロックされるので置き換えることができない。ただし、{}->propとprop->5の参照はロックされていないので入れ替えが可能。

なので以下のようにオブジェクトの中身を変えることもできる。
良い反面、値が追いにくくなるので書くときに注意。
```javascript
const a = {
    prop: 5;
}

const b = a
a.prop = 6
b.newprop = 10

console.log(a); // { prop: 6, newprop: 10 }
console.log(b); // { prop: 6, newprop: 10 }
console.log(a === b); // true （同じオブジェクトを参照している）
```
# 分割代入
分割代入すると新しいオブジェクトを作成するので元のオブジェクトに影響がないように作成できる
```javascript
// 1. 最初の状態
const a = {
    prop: 'hello'
};

// 2. 分割代入
const { prop } = a;  // prop = 'hello' として新しい変数を作成
prop = 'bye';

console.log(a.prop);  // 'hello' （元のオブジェクトは変更されていない）
```