JavaScript

JavaScriptの参照に注意【オブジェクト型の特有な動き】

どうも、つよぽんです!

今回は、JavaScriptの参照の動きについて解説します。

今回の記事は次のような方に向けて書きました。

想定読者
  • 参照って何?
  • 変数に値を代入するときにプリミティブ型の値とオブジェクト型の値でどんな違いがあるか知りたい

この記事では「オブジェクト型の参照の概念」ついて解説していくので、この記事を読み終わる頃には次のことがわかるようになります。

この記事を読み終えた後のあなた
  • 参照とはどういうものか理解するようになる
  • オブジェクト型の値を関数の引数として渡したり、別の変数に代入するときに何をすればよいかわかるようになる

今回の記事は以下の学習コンテンツのスライドを詳しく解説した記事となります。以下の記事と合わせて読むことでより理解度を深めていただけるかと思います。

あわせて読みたい
JavaScriptの配列で参照を理解する【オブジェクト型の動き】今回はJavaScriptの参照の学習をします。プリミティブ型とオブジェクト型で変数に値を代入するときの動きは異なります。プリミティブ型は値そのものが代入され、オブジェクト型は「参照」が代入されます。参照が何か理解して参照を使いこなせるようになりましょう。...

それでは次の内容で話を進めていきます。

今回の内容
  1. JavaScriptの参照とは
  2. JavaScriptの参照を変数に代入するときの注意点

JavaScriptの参照とは

この章では、「JavaScriptの参照とは何か?」について解説していきます。

参照とは、一言で言うと「オブジェクト型の値が保存されているエリア」のことです。

言葉だけではイメージが付きづらいと思うので、プリミティブ型の値が変数に保存される場合と、オブジェクト型の値が変数に保存される場合で画像を使って比較していきます。

プリミティブ型の値を変数に保存する場合

以下の画像は「プリミティブ型の値を変数に代入したときのイメージ」になります。

プリミティブ型の値が変数に保存されている時のイメージプリミティブ型の値が変数に保存されている時のイメージ

画像の説明に書いている通り、値がそのまま変数に直接格納されるイメージとなります。

上の画像で使っている値を例にして、「const number2 = number;」のように「変数number」に保存されている値を新しく「変数number2」に代入した場合、「変数number2」には直接10が格納されます。

オブジェクト型の値を変数に保存する場合

以下の画像は「オブジェクト型の値を変数に代入したときのイメージ」になります。

オブジェクト型の値が変数に保存されている時のイメージオブジェクト型の値が変数に保存されている時のイメージ

画像の説明に書いている通り、変数にはオブジェクト型の値が直接保存されるわけではなく、「参照」という形式で間接的にオブジェクト型の値にアクセスします。

そして、この時オブジェクト型の値、つまり参照を保存している変数を別の変数に代入したときは、同じ参照を共有することになります。

以下の画像は同じ参照を共有しているイメージをあらわしたものです。

参照を保持する変数を別に変数に代入したときのイメージ(参照の共有)参照を保持する変数を別に変数に代入したときのイメージ(参照の共有)

上の画像では「変数numberList1」「変数numberList2」には同じ参照情報が保存されています。

この参照情報の先、つまり上の画像だと「参照A」が、この章の始めの方で話した「オブジェクト型の値が保存されているエリア」ということになります。

JavaScriptの参照を変数に代入するときの注意点

この章では、「参照を変数に代入するときの注意点」について解説します。

ここで話す注意点を一言でまとめると、「参照先の値を別の変数に代入したいときは参照のコピーを渡す」ということです。

参照をそのまま渡した場合」「参照のコピーを渡した場合」でどんな違いがあるのか、それぞれ説明していきます。

参照の値を変更すると、同じ参照を持つ他の変数の値も一緒に変更される

この項目では「参照をそのまま渡した場合」について解説します。

以下の画像は「const numberList2 = numberList1」のように、同じ参照先をそのまま別の変数に渡したときの様子を表したものです。

同じ参照を持つ全ての変数に影響を与える同じ参照を持つ全ての変数に影響を与える

このとき、参照先の値を更新すると、同じ参照先を保持している変数の値は全て同時に変更されてしまいます。

以下のサンプルコードは「numberList1.push(4)」で「numberList1」に対して値を更新したコードですが、「numberList2」にも「numberList1.push(4)」の影響で4が追加されています。

他の変数にも影響を与えていることを表している様子他の変数にも影響を与えていることを表している様子

この挙動がオブジェクト型の値を取り扱うときに注意しなければいけない点です。

この問題を防ぐためには、次の項目で紹介する「参照先のコピーを渡す」ということをすれば解決します。

上の画像内のサンプルコードは以下のリンク先から直接確認できます。

配列を使った参照のサンプル1

参照を共有しないで、参照内の値のコピーを渡すことで別の変数に影響を与えないようにする

この項目では「参照のコピーを渡した場合」について解説します。

以下の画像では「const numberList2 = numberList1.slice()」で、参照先のコピーを「numberList2」に渡したことを説明しています。

参照先のコピーを渡して、それぞれ独立した参照を持つ変数にする参照先のコピーを渡して、それぞれ独立した参照を持つ変数にする

Array.prototype.slice()」を使うと配列のコピーを作ること出来ます。

参照先のコピーを渡したことにより、「numberList1」は「参照A」を持ち、「numberList2」は「参照B」を持ち、それぞれ異なる参照先を見ることになります。

そのため、「numberList1.push(4)」とnumberList1の値を更新しても、別の参照を持つnumberList2は全く影響を受けずに済みます。(以下の画像で説明)

参照Aを更新しても参照Bには影響はない参照Aを更新しても参照Bには影響はない

以下のサンプルコードでは「numberList1.push(4)」で「numberList1」に対して値を更新しても、「numberList2」には影響を出ていないことがわかります。

参照先が違っていれば他の変数には影響がないことを表したサンプルコード参照先が違っていれば他の変数には影響がないことを表したサンプルコード

このように、参照先の値をコピーすればいつのまにか変数に保存している値が書き換わったという意図しない挙動を未然に防ぐことが出来ます。

上の画像内のサンプルコードは以下のリンク先から直接確認できます。

配列を使った参照のサンプル2

まとめ

今回の話をまとめると次のとおりです。

今回のまとめ
  • オブジェクト型が変数に代入されるときは「参照」が保存される
  • 同じ参照先を持つ変数は互いに影響を与え合うので注意が必要
  • オブジェクト型の意図しない上書きを防ぐためには「参照先のコピー」を別の変数に渡せば良い

今回の内容は以下の記事内のスライドの補足資料として作成しました。スライドの全部を確認したい方は以下の記事も参照して頂けたらと思います。

あわせて読みたい
JavaScriptの配列で参照を理解する【オブジェクト型の動き】今回はJavaScriptの参照の学習をします。プリミティブ型とオブジェクト型で変数に値を代入するときの動きは異なります。プリミティブ型は値そのものが代入され、オブジェクト型は「参照」が代入されます。参照が何か理解して参照を使いこなせるようになりましょう。...
【やる気満々な方向け】学習サポートとオンライン講義やってます!

Webエンジニアになりたい人向けに、MENTAにて『【やる気満々な方向け】未経験からのWebエンジニア育成コース』というプランを用意しております。

このプランでは、「【学習コンテンツ】Web開発」と「【初心者向け】The Web Developer Bootcamp」で紹介している教材を使って学習を進めていただきます。

【学習コンテンツ】Web開発」に用意している学習コンテンツのスライドも「【初心者向け】The Web Developer Bootcamp」で紹介している教材をベースに作っています。

あわせて読みたい
【初心者向け】The Web Developer Bootcampはじめに 「The Web Developer Bootcamp」はWeb白熱教室の「学習コンテンツ」のベースとなっている教材です。 ...
あわせて読みたい
Web開発Webエンジニアになるために必要な知識・スキルを学習できるコンテンツを用意しました。未経験者でも、①開発環境の準備、②Webの基本的な仕組み、③HTML、④CSS、⑤JavaScriptと順を追って学習することでスキルが身につくことを目的に教材を作成しています。...

誰向けのプラン?

こちらのプランは次のような方に向けて作られています。

プラン対象者
  1. Progateやドットインストールで一通り学習したけど、次に何をすればよいかわからない
  2. Webエンジニアになるまでの学習プランがあると助かる
  3. 学習していてわからないところが出てきたときに質問したい
  4. コードレビューして欲しい
  5. オンライン講義に参加したい
  6. 学習した内容をアウトプットした際に、フィードバックがもらえたら嬉しい
  7. おすすめの学習教材を知りたい
  8. Webフロントエンド・バックエンドを学習したい
  9. フルスタックエンジニアになりたい
  10. 文系出身で今までプログラミングをしてこなかったけど、将来Webエンジニアになりたい
  11. 将来フリーランスになることを目指している

プラン内容は?

【やる気満々な方向け】未経験からのWebエンジニア育成コース』では次のことを行っております。

プラン内容
  1. Udemyの教材や、Web白熱教室の学習コンテンツを使った学習プランの提示 (学習プランに沿って学習を進めていただきます。)
  2. 教材・学習コンテンツの課題をこなしたあとは、僕にコードレビュー依頼を投げていただくことで、コードを添削する(課題クリア後は、引き続き学習プランの内容を続けていただきます。)
  3. プラン契約者が参加するSlackグループにて質問し放題
  4. Slack内にある「アウトプットの場」チャンネルにて、学習したことをアウトプットをしていただくことで、それに対しフィードバックをする (学習内容のアウトプットは復習にもなるため、アウトプットすることを強く推奨します。)
  5. 画面共有を使ったオンライン講義 (オンライン講義は録画して、いつでもふり返れるようにしています。(オンライン講義動画(ウェビナー動画)))
  6. 学習プラン以外の内容に対しての質疑応答 (内容によっては回答できないものもありますが、まずは気軽に質問していただけたらと思います。)

その他注意点

1人で対応していることもあるため、対応が難しくなった場合は急遽募集を終了する可能性もあることをご了承ください。

もしくは、僕以外にメンターを増やすことで募集を継続するということも考えているため、その場合は現在のプラン料金の値段を上げることなると思います。

仮にプラン料金を上げる場合は、『現在のプラン料金 × メンター人数』の料金になるかと思います。

現在の値段が5000円なので、1日1本ペットボトルジュースを買うのを我慢することで(約160円)、効率よく学習できるので費用対効果はかなり高いかなと自負しています。

また、今後メンターが増えて、プラン料金が10000円15000円と上がったとしても、月々の料金は申し込んだときの料金となるので、5000円のときに契約した場合はずっと5000円で受講することができます。

詳しく話を聞いてみたい方は

以下のいずれかでメッセージをいただけたらと思います^^

 

プラン内容については以下のリンク先からも確認することが出来ます^^

【やる気満々な方向け】未経験からのWebエンジニア育成コース

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です