【JavaScript】JavaScriptにおける変数の参照について図解で理解する。

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。

###疑問１

```javascript
let a = { prop1: "dog", prop2: "cat" };
let b = { prop1: "dog", prop2: "cat" };

console.log(a === b);
```

これはtrueかfalseか？
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問２

```javascript
let a = { prop1: "dog", prop2: "cat" };
let b = a;

console.log(a === b);
```
これはtrueかfalseか？
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問３

```javascript
const a = { prop1: "dog", prop2: "cat" };

a.prop1 = "rabbit";
```
エラーとなるのか？
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問４

```javascript
const a = { prop1: "dog", prop2: "cat" };

const b = a;

b.prop1 = "rabbit";

console.log(a.prop1);
`````````
出力されるのは　dog か rabbit　か

##変数とデータ型
JavaScriptのデータ型は８種類

 - Boolean
 - Number
 - String
 - Undefined
 - Null
 - Symbol
 - Bigint
 - Object

##プリミティブ型とオブジェクト型
データ型のうちObjectはオブジェクト型、それ以外をプリミティブ型という。

####プリミティブ型の特徴

 - 変数には**値**が格納される。
 - 値を変更することが**できない。(イミュータブル）**
 
####オブジェクト型の特徴
 - 変数には**参照情報**が格納される。
 - 値を変更することが**できる。(ミュータブル）**

```javascript
let a = 1;
a = 2 ;
```
この場合、a は　変更できるのではなか？

メモリ空間上での参照を変更しているだけでメモリ上の値は変更されていない。(注：厳密ではなくイメージ）

```メモリ空間

メモリ3        メモリ１        メモリ2
　             a    ---->   1       : let a = 1
　2   <----    a                    :     a = 2
```

##constがロックしているもの
constは、この**参照先の変更**をロックしている。

```メモリ空間.

メモリ3           メモリ１           メモリ2
　                 a      ---->    1           : const a = 1
　  2   <-❌--     a                           :        a = 2
```

##オブジェクトのメモリ上の動き(注：厳密ではなくイメージ）

```JavaScript
let a = {
  prop : "dog"
}
```
この場合

```メモリ空間.

メモリ3       メモリ１        　メモリ2            メモリ4        メモリ5
　              a 　　----> メモリ4を参照　---->   {prop} ---->  "dog"
```    
このようにオブジェクト型　a には値ではなく、**参照情報**が格納されている。
この時、メモリ5の内容が変わったとしてもメモリ2自体（メモリ４を参照してね。という情報）は変わらないので、同一オブジェクトを参照する。
これがイミュータブルと言われる由縁。

##プリミティブ型の値のコピー
```javascript
let a = "dog";
let b = a;
b = "cat";
```
```メモリ空間

メモリ3   メモリ１  　　メモリ2    メモリ4   　メモリ5
　          a --> "dog"　                      : let a = "dog"
                           b  --> "dog"     : let b = a
//この時同じメモリ2を参照するのではなく、異るメモリ上に同じ値がコピーされている。

"cat"  <-------------------　b      "dog"     : b = "cat"
//参照先メモリが変更される。
```
もちろん

```javascript
console.log(a)
//dog
```
aには影響しない。

##オブジェクト型の値のコピー

```javascript
let a = {
  prop:"dog"
};

let b = a;
b.prop = "cat";
```

```メモリ空間

メモリ１　　    メモリ2　　　     メモリ3　     メモリ4　   メモリ6　   メモリ7　   メモリ8
  a  -> メモリ3参照　 -> {prop} --> "dog"                             : let a = {prop:"dog"};
                                          b --> メモリ3参照         : let b = a;
//参照情報がコピーされる。 

   　　　　　　　　　　　             {prop} ---------------------------> "cat"   :b.prop = "cat"
//メモリ３のpropの参照がメモリ4からメモリ8に変更。
//aとb 同じメモリー3を参照している。 
```
よって、この場合、bのオブジェクト内部の変更はaにも影響してくる。

##オブジェクト型のconstへの再代入

```javascript
const a = {
  prop:"dog"
};

a =  {}
```

```メモリ空間.

メモリ6       　   　メモリ１        　メモリ2          メモリ4        メモリ5     メモリ6
　           　　     a 　　----> メモリ4を参照　---->  {prop} ----> "dog"
メモリ６を参照 <-❌-  a                                                   {}
```    
これは constでロックさているためエラーとなる。
{pops:"dog"}と異なる新しいオブジェクト{}がメモリ６に作成され、参照先をそのメモリ６に変更しようとするとエラーとなる。

```javascript
const a = {
  prop:"dog"
};

a.prop = "cat"
```
↑この場合↓  

```メモリ空間.

メモリ3       　 　メモリ１        　メモリ2            メモリ4        メモリ5    
　           　　  　　　a 　--->   メモリ4を参照　---->   {prop}  ----> "dog"
"cat" <-------------------------------------{prop}        "dog"                                                  
```   
constでロックしているのはあくまでaの参照先であり、メモリ４のオブジェクト内部の値は変更できる。

また、関数の仮引数に実引数を渡す場合、同様のコピーが行われる。

```javascript
function fn(obj){
  obj.prop1="dog";
}

const obj ={prop1:"cat"}

fn(obj)

console.log(obj.prop1);
//dog
```


##疑問を振り返る。

##疑問１

```javascript
let a = { prop1: "dog", prop2: "cat" };
let b = { prop1: "dog", prop2: "cat" };

console.log(a === b);
```

これはtrueかfalseか？

「false」

a　と　b　では　異る参照情報を保持しているため。


```メモリ空間

メモリ１　　   　メモリ2　　　      メモリ3　  メモリ4　     メモリ6　       メモリ7　   
  a -->　メモリ3を参照 ->  {略}
　　　　　　　　　　　　　　　　　　　　　　　                    b --->　メモリ7を参照 --->{略}

　　メモリ3を参照 ≠　メモリ7を参照
```
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
##疑問２

```javascript
let a = { prop1: "dog", prop2: "cat" };
let b = a;

console.log(a === b);
```
これはtrueかfalseか？

「true」

```メモリ空間

メモリ１　　   　  メモリ2　　　      メモリ3　   メモリ4　   メモリ5  
  a --->　メモリ3を参照 -->  {略}
　　　　　　　　　　　　　　　　　                          b -->メモリ3を参照

//オブジェクト型なので参照情報がコピーされる。

"メモリ3を参照" と　"メモリ3を参照"　　　同値
```
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問３

```javascript
const a = { prop1: "dog", prop2: "cat" };

a.prop1 = "rabbit";
```
エラーとなるのか？
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
「ならない」

constでaをロックしているのは、参照情報について。参照情報が変更されるわけではない。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問４

```javascript
const a = { prop1: "dog", prop2: "cat" };

const b = a;

b.prop1 = "rabbit";

console.log(a.prop1);
`````````
出力されるのは　dog か rabbit　か

「rabbit」

const b = a;で参照情報がコピーされるので同じオブジェクトを参照する。
当然同じオブジェクトを参照しているaにも影響がでる。