8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2020-11-23

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

###疑問1

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

console.log(a === b);

これはtrueかfalseか?
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問2

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

console.log(a === b);

これはtrueかfalseか?
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問3

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

a.prop1 = "rabbit";

エラーとなるのか?
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問4

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

const b = a;

b.prop1 = "rabbit";

console.log(a.prop1);

出力されるのは dog か rabbit か

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

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

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

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

  • 変数にはが格納される。
  • 値を変更することができない。(イミュータブル)

####オブジェクト型の特徴

  • 変数には参照情報が格納される。
  • 値を変更することができる。(ミュータブル)
let a = 1;
a = 2 ;

この場合、a は 変更できるのではなか?

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


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

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

メモリ空間.

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

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

let a = {
  prop : "dog"
}

この場合

メモリ空間.

メモリ3       メモリ1         メモリ2            メモリ4        メモリ5
               a   ----> メモリ4を参照 ---->   {prop} ---->  "dog"

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

##プリミティブ型の値のコピー

let a = "dog";
let b = a;
b = "cat";

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

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

もちろん

console.log(a)
//dog

aには影響しない。

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

let a = {
  prop:"dog"
};

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

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

                           {prop} ---------------------------> "cat"   :b.prop = "cat"
//メモリ3のpropの参照がメモリ4からメモリ8に変更。
//aとb 同じメモリー3を参照している。 

よって、この場合、bのオブジェクト内部の変更はaにも影響してくる。

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

const a = {
  prop:"dog"
};

a =  {}
メモリ空間.

メモリ6            メモリ1         メモリ2          メモリ4        メモリ5     メモリ6
                   a   ----> メモリ4を参照 ---->  {prop} ----> "dog"
メモリ6を参照 <-❌-  a                                                   {}

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

const a = {
  prop:"dog"
};

a.prop = "cat"

↑この場合↓

メモリ空間.

メモリ3          メモリ1         メモリ2            メモリ4        メモリ5    
                   a  --->   メモリ4を参照 ---->   {prop}  ----> "dog"
"cat" <-------------------------------------{prop}        "dog"                                                  

constでロックしているのはあくまでaの参照先であり、メモリ4のオブジェクト内部の値は変更できる。

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

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

const obj ={prop1:"cat"}

fn(obj)

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

##疑問を振り返る。

##疑問1

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

console.log(a === b);

これはtrueかfalseか?

「false」

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


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

  メモリ3を参照 ≠ メモリ7を参照

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
##疑問2

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

console.log(a === b);

これはtrueかfalseか?

「true」


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

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

"メモリ3を参照" と "メモリ3を参照"   同値

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問3

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

a.prop1 = "rabbit";

エラーとなるのか?
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
「ならない」

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

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
###疑問4

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

const b = a;

b.prop1 = "rabbit";

console.log(a.prop1);

出力されるのは dog か rabbit か

「rabbit」

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

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?