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開発」を使って学習を進めていただきます。

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

誰向けのプラン?

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

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

プラン内容は?

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

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

その他注意点

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

プラン契約者数が35人に達したら値上げする予定です

現在の値段は10000円です。

つまり、「月の飲み会3回くらいの金額」となります。

飲み会に行く代わりに、学習時間を優先すると考えれば自己投資としてはだいぶリーズナブルかと思います。

1日1回、カフェでコーヒー1杯分くらいの値段(約330円)」で以下の環境が手に入るとイメージして頂けたらと思います。

1日330円で手に入る環境
  1. コードを添削してもらえる
  2. 学習したことのアウトプットに対してフィードバックしてもらえる
  3. いつでも質問出来る
  4. 週1のオンライン講義に参加できる
  5. 過去のオンライン講義動画を好きな時間に復習できる(いつでも閲覧可能)
  6. 不定期で行うオフラインでの勉強会に参加できる(僕自身が東京住みのため、東京・もしくは東京近郊で開催します)
  7. 自分の住まいの近場のメンティーさん同士で集まって、オフラインで勉強会を開くのも可能(初めて開催する場合は事前に僕に連絡をいただけたらと思います)

ただ、プラン契約者数が35人に達したら15000円値上げする予定です。
(2019年2月13日現在のプラン契約者数は27人)

値上げする理由は次のとおりです。

値上げ理由
  1. このプランを始めた当初(2018年9月)と比べて、学習コンテンツ(スライド・課題・動画)が充実してきた
  2. このプランに参加していただいているメンティーさんの中から、「Web未経験から学習を初めて2~3ヵ月くらいで案件獲得までこぎつけることができた」という実績ができた
  3. 学習サポート(コードレビューや質疑応答など)を1人で行っており、人数が増えすぎるとサポートに支障が出てくるため、値上げという形で参加ハードルをあげた
    (人数を制限することによりサポートの質を維持するため)

今後も契約者が増えたり、学習コンテンツがさらに充実していった場合は段階的に料金改定させていただく予定です。

契約した時点の金額がずっと継続される

現在、学習プランを提供しているプラットフォームである「MENTA」の性質上、契約した時点の金額は変わることがありません。

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

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

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

 

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

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

COMMENT

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