# プリミティブ型とオブジェクト型の違い

constでオブジェクト型のものは値の中身を変更することができ、プリミティブ型は変更ができない点に関して、詳細に説明します。

内部的に見ると、変数は特定のメモリのアドレスを格納しますが、プリミティブ型とオブジェクト型で挙動が異なります。

まずプリミティブ型は、下の図で説明すると、`let name1 = 'tarou'`とすると、`tarou`がメモリの特定の場所(`0x0001`)に格納されます。格納された場所を表すものを**アドレス**と言うのですが、`name1`が値を保持する0x0001に紐づいて、別の場所に保存されます(`0x0002`)。

この時`let name2 = name1`とコピーしたとすると、`name2`も`0x0001`というアドレスを参照していることを`0x0003`というアドレスに格納されます。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2F6kkKtXbGMoc6Yx4gsjXl%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-11-30%2017.45.07.png?alt=media&#x26;token=f9fa9b83-fd8b-4c12-bd50-dc5051279c09" alt=""><figcaption></figcaption></figure>

その後`name1 = 'jirou'`と上書きしたとすると、`jirou`が別のアドレス(0x0004)に格納され、`name1`の参照先がそのアドレスに書き換えられます。ですので、`name2`の値は変わりません。このようにメモリに格納された値自体を変えることができません。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FSJSbJLjKgEEY5AxCrBq4%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-11-30%2017.45.58.png?alt=media&#x26;token=ec1af590-854f-4ae5-8372-f2f7f38bbcd2" alt=""><figcaption></figcaption></figure>

<pre class="language-javascript" data-title="index.js◎"><code class="lang-javascript">...
console.log(product);

<strong>let name1 = 'tarou';
</strong><strong>let name2 = name1;
</strong><strong>name1 = 'jirou';
</strong><strong>console.log(name1);
</strong><strong>console.log(name2);
</strong></code></pre>

一方でオブジェクト型は、`let product1 = {...}`と定義した際に、各プロパティの値が各アドレス(`0x0001`, `0x0002`)に格納され、その値に対応するkeyの情報も各アドレス(`0x0003`, `0x0004`)に格納され、それら全てのプロパティを参照しているアドレスを一つのアドレス(`0x0005`)に格納し、それをproduct1が参照する(`0x0006`)ようになっています。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FH4ROdS6OjSx1AxEsswnK%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-11-30%2017.52.45.png?alt=media&#x26;token=c48a3d5b-ebe5-4a95-b91a-4b33880ef648" alt=""><figcaption></figcaption></figure>

この時、`let product2 = product1`とコピーしたとすると、`product2`も`0x0005`というアドレスを参照していることを`0x0007`というアドレスに格納されます。

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FrKLINW4bQx3GusbmMyJG%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-11-30%2018.00.25.png?alt=media&#x26;token=0deb1c1f-8f93-40f1-a59f-076a15a0c6e4" alt=""><figcaption></figcaption></figure>

ここで、`product1.name = 'みかん'`とプロパティの値を変更したとします。そうすると、`みかん`という値が別のアドレスに格納され、`name`の参照アドレスが変更されます。ですので、`product2`の`name`も`みかん`に変わります。また、`const`で定義した際に、なぜプロパティを変更できるのかというと、`const`は内部的な挙動として、**定義した定数の参照先アドレスを変えるとエラーとなるので**、**参照先の参照先が変更する場合はエラーとなりません。**

<figure><img src="https://1869761657-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcUBbYqol4PMzZJggiMqV%2Fuploads%2FLteWxPOILVLPPAQhuREv%2F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202023-11-30%2018.04.45.png?alt=media&#x26;token=999ef883-e55f-4843-8b13-5d217e2b33dd" alt=""><figcaption></figcaption></figure>

<pre class="language-javascript" data-title="index.js◎"><code class="lang-javascript">...
console.log(name2);

<strong>const product1 = {
</strong><strong>  name: "りんご",
</strong><strong>  price: 100,
</strong><strong>};
</strong><strong>let product2 = product1;
</strong><strong>product1.name = 'みかん';
</strong><strong>console.log(product1);
</strong><strong>console.log(product2);
</strong></code></pre>

まとめると、

* プリミティブ型の変数は値をコピーした際に、元の値を上書きしても、コピー先は変わらない。constで定義したものは値を変更することができない。
* オブジェクト型の変数は値をコピーした際に、元の値（keyや要素）を変更した際に、コピー先も変わる。constで定義しても、keyや要素を変更することができる。
