IORI online School

JavaScript、html、css の無料学習サイト

【JavaScript 中級講座】値渡しと参照渡し

[JavaScript 中級講座]値渡しと参照渡し

本講座では、値渡しと参照渡しについて学習する。 値渡しも参照渡しも、多くのプログラミング言語に関係する、非常に重要な概念である。
本講座はJavaScriptの勉強というより、 プログラミングの基礎的内容をJavaScriptで学習する、という意味合いが強い。

値渡し

まず、値渡しから学習する。簡単な内容であるが、集中して学習してほしい。

001<script>
002//変数を宣言
003var a = 10 ;
004var b = 5 ;
005
006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a ) ;
008alert ( "b:" + b ) ;
009
010//変数aの値をbへ代入
011b = a ;
012
013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a ) ;
015alert ( "b:" + b ) ;
016
017//変数aの値を変更
018a = 20 ;
019
020//それぞれ表示[a:20][b:10]
021alert ( "a:" + a ) ;
022alert ( "b:" + b ) ;
023</script>
プログラムを実行すると、
a:10
b:5

a:10
b:10

a:20
b:10
と表示する。

長いプログラムなので、分割して解説する。

001<script>
002//変数を宣言
003var a = 10 ;
004var b = 5 ;

3行目と4行目で変数a、bを宣言して、それぞれ「10」と「5」を代入する。 この時コンピューター上には、変数が2つ作成される。

変数
a 10
b 5

このような状態である。簡単である。最初は簡単である。今後この表が複雑になる。

003var a = 10 ;
004var b = 5 ;
005
006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a ) ;
008alert ( "b:" + b ) ;

7行目と8行目で、変数の値をそれぞれ表示する。
「a:10」と「b:5」が表示する。

006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a ) ;
008alert ( "b:" + b ) ;
009
010//変数aの値をbへ代入
011b = a ;

11行目で、変数aの値を変数bへ代入する。

値渡し
値をコピーして渡す。

値渡しとは、変数に入っている値を コピーして渡す事である。 いま、変数aに値「10」が入っている。 11行目で、変数aの値をコピーして、変数bへ代入する。

変数
a 10
b 10

コンピューターは、このようになる。

010//変数aの値をbへ代入
011b = a ;
012
013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a ) ;
015alert ( "b:" + b ) ;
016
017//変数aの値を変更
018a = 20 ;

11行目で変数aの値を変数bへ代入した後、14行目と15行目でそれぞれの値を表示する。
「a:10」「b:10」と表示する。
18行目を解説する。 18行目で、変数aに「20」を代入する。 この時、元々変数aに代入されていた「10」の値は上書きされる。

変数
a 20
b 10

コンピューターは、このようになる。 この部分が「値渡し」と「参照渡し」の差異になるので、もう一度解説する。 変数aに新しい値「20」を代入した。 この時、変数bの値は変更されない。 「当たり前」と思う方もいらっしゃるだろうが、「参照渡し」の学習で最も重要な話になるので、 覚えてほしい。

018a = 20 ;
019
020//それぞれ表示[a:20][b:10]
021alert ( "a:" + a ) ;
022alert ( "b:" + b ) ;
023</script>

プログラムの最後で、変数aとbの値を表示する。 「a:20」「b:10」と表示してプログラムが終了する。 以上が値渡しである。

オブジェクトを作成して変数へ代入する

参照渡しの解説をする前に、 「オブジェクトを変数へ代入する」という意味を正確に解説する。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004</script>

3行目を詳しく見る。まず、「 = 」の右側でオブジェクトが生成される。 コンピューター上にオブジェクトが作られる。

オブジェクト
{ x : 10 }

これが、オブジェクトを生成するという意味である。 さて、オブジェクトを生成すると、戻り値として「参照」が戻る。

参照
オブジェクトへの参照。 オブジェクトを参照するためのアドレスである。

参照とは、オブジェクトを参照するための値である。 実際はオブジェクトが存在するアドレス値である。 しかし参照の値を、プログラマーが意識する必要は全く無い。 「オブジェクトを生成すると、オブジェクトを参照するための参照が戻る」 という事実のみ意識する必要がある。

イメージ
オブジェクトを作っても、オブジェクトに名前がなければ利用できない。 参照とは、オブジェクトの名前である。

参照とはアドレスである。これが事実である。 しかし、アドレスと言ってもイメージする事が難しい。 「参照はオブジェクトの名前」とイメージすると良い。
オブジェクトを生成すると、コンピューター上にオブジェクトができる。 コンピューター上にオブジェクトができるのは良いが、名前がなければ利用できない。 そこで、オブジェクトに名前を付ける。それが参照である(というイメージである)。 オブジェクトを生成すると、オブジェクトの名前(参照)が戻される。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004</script>

3行目で変数aを宣言して、オブジェクトの参照を受け取っている。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }

この表は重要である。 解説する。まず、変数aには参照「参照-1」が入っている。 この参照はオブジェクトの名前である。 オブジェクトを利用する場合、この参照(名前)を利用する。 通常、参照の値を意識する必要は無い。しかし、「参照渡し」を学習する際、 「参照-1」のように、具体的な値を例示したほうが理解が進む。 ちなみに、「参照-1」は解説用の参照の例であって、実際の値とは異なる。 注意してほしい。実際の参照の値は分からない。
さて、参照「参照-1」が参照しているオブジェクトは
{ x : 10 }である。 オブジェクト{ x : 10 }を利用するためには、 この参照「参照-1」(「オブジェクトの名前」というイメージ)が必要である。
解説は以上である。

メモリ上にオブジェクトを展開

オブジェクトの存在がもっと身近になるように、サンプルを見る。 (まだ、参照渡しの学習に入っていない。参照渡しを理解するための準備段階である)

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 10 } ;
005</script>

3行目で変数aを宣言して、オブジェクトの参照を代入する。 4行目で変数bを宣言して、オブジェクトの参照を代入する。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-2 { x : 10 }

コンピューターはこのようになる。 まず、3行目で、オブジェクト
{ x : 10 }
が生成され、オブジェクトの参照が戻される。 その参照を変数aで受け取る。これが3行目の処理である。 表の中では、参照を「参照-1」と表現している。
つぎに、4行目で、オブジェクト
{ x : 10 }
が生成され、オブジェクトの参照が戻される。 その参照を変数bで受け取る。これが4行目の処理である。 表の中では、参照を「参照-2」と表現している。

参照する
変数にオブジェクトの参照が入っている場合、 「変数が参照するオブジェクト」と表現する。

いま、変数a、bの中にオブジェクトの参照が入っている。 この場合、オブジェクトの事を「変数aが参照するオブジェクト」「変数bが参照するオブジェクト」 と表現する。
さて、 変数aとbが参照するオブジェクトは同じ構造を持っている。 しかし、実際は二つのオブジェクトが生成され、コンピューター上に存在する。

メモリ上のオブジェクトを理解する

参照渡しを理解するための準備をする。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 10 } ;
005
006a.x = 20 ;
007
008//表示[a:20][b:10]
009alert ( "a:" + a.x ) ;
010alert ( "b:" + b.x ) ;
011</script>
プログラムを実行すると、「a:20」「b:10」と表示する

プログラムを解説する。3行目で変数aを宣言してオブジェクトを代入する。 4行目で変数bを宣言してオブジェクトを代入する。 「オブジェクトを代入」と解説したが、実際はオブジェクトの参照を 変数a、bへ代入する。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-2 { x : 10 }

3行目と4行目が終了した時点で、コンピューター上に二つのオブジェクトが存在する。

006a.x = 20 ;
007
008//表示[a:20][b:10]
009alert ( "a:" + a.x ) ;
010alert ( "b:" + b.x ) ;
011</script>

6行目を解説する。6行目で変数aが参照するオブジェクトのxプロパティへ「20」を代入する。

変数 参照(例示) オブジェクト
a 参照-1 { x : 20 }
b 参照-2 { x : 10 }

6行目を実行すると、変数aが参照するオブジェクトのxプロパティに「20」が入る。 変数bが参照するオブジェクトは変更しない。 変数aと変数bが参照するオブジェクトは、別々のオブジェクトなので、 変数aが参照するオブジェクトが変更されても、変数bが参照するオブジェクトに影響しない。

008//表示[a:20][b:10]
009alert ( "a:" + a.x ) ;
010alert ( "b:" + b.x ) ;
011</script>

9行目と10行目で変数a、bが参照するオブジェクトのxプロパティの値を表示する。 プログラムを実行すると、「a:20」「b:10」と表示する。

参照渡しを実行する

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//参照渡し
007b = a ;
008</script>

参照渡しをするプログラムである。 3行目と4行目でオブジェクトを生成して、オブジェクトの参照を変数a、bへ代入する。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-2 { x : 5 }

コンピューターはこのような状態になる。 7行目で、変数aの値を変数bへ代入して、参照渡しをする。

参照渡し
オブジェクトの参照をコピーして、別の変数へ代入する事

サンプルの7行目で、変数aの参照を変数bへ代入する。 これを参照渡しと言う。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-1

変数aに入っている参照は「参照-1」であった(「参照-1」は実際の値ではなくて、例示である)。 この値がコピーされ、変数bへ代入される。 変数bには、もともと「参照-2」が入っていた。 これが上書きされる。 もともと変数bが参照していたオブジェクト
{ x : 5 }
は、どこかへ消える。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//参照渡し
007b = a ;
008</script>

7行目を実行すると、変数aと変数bは同じオブジェクトを参照する。

参照渡しの動作確認

参照渡しの動作をまとめたサンプルプログラムを掲載する。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a.x ) ;
008alert ( "b:" + b.x ) ;
009
010//aのオブジェクトをbへ代入
011b = a ;
012
013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a.x ) ;
015alert ( "b:" + b.x ) ;
016
017//変数aのオブジェクトを変更
018a.x = 20 ;
019
020//それぞれ表示[a:20][b:20]
021alert ( "a:" + a.x ) ;
022alert ( "b:" + b.x ) ;
023</script>
プログラムを実行すると

「a:10」
「b:5」

「a:10」
「b:10」

「a:20」
「b:20」

と表示する。

参照渡しの動作を確認するプログラムである。 プログラムを分割しながら解説する。

002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a.x ) ;
008alert ( "b:" + b.x ) ;
変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-2 { x : 5 }

3行目と4行目でオブジェクトを作成して、それぞれ変数aと変数bへ代入する。 3行目と4行目を実行すると、コンピューター上にオブジェクトが2つできる。 7行目と8行目で、変数aとbが参照するオブジェクトのxプロパティの値を表示する。
プログラムを実行すると、 「a:10」「b:5」と表示する。

007alert ( "a:" + a.x ) ;
008alert ( "b:" + b.x ) ;
009
010//aのオブジェクトをbへ代入
011b = a ;
012
013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a.x ) ;
015alert ( "b:" + b.x ) ;

11行目が参照渡しのプログラムである。変数aに入っている参照をコピーして、 変数bへ代入する。 この時、変数bに入っていた参照は、上書きされて消える。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-1

変数aに入っていた値「参照-1」がコピーされて、変数bに代入される。 変数aとbは、同じオブジェクトを参照する。

010//aのオブジェクトをbへ代入
011b = a ;
012
013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a.x ) ;
015alert ( "b:" + b.x ) ;

14行目と15行目で、変数aとbが参照するオブジェクトのxプロパティの値を表示する。 変数aと変数bは同じオブジェクトを参照しており、xプロパティの値は「10」である。 プログラムを実行すると、
「a:10」「b:10」と表示する。

013//それぞれ表示[a:10][b:10]
014alert ( "a:" + a.x ) ;
015alert ( "b:" + b.x ) ;
016
017//変数aのオブジェクトを変更
018a.x = 20 ;
019
020//それぞれ表示[a:20][b:20]
021alert ( "a:" + a.x ) ;
022alert ( "b:" + b.x ) ;
023</script>

18行目で変数aが参照するオブジェクトのxプロパティに「20」を代入する。

変数 参照(例示) オブジェクト
a 参照-1 { x : 20 }
b 参照-1

変数aが参照するオブジェクトと変数bが参照するオブジェクトは同じである。 変数aが参照するオブジェクトのxプロパティを変更するというのは、 すなわち、変数bが参照するオブジェクトのxプロパティを変更するという意味である。 プログラムの21行目と22行目で、オブジェクトのxプロパティを表示すると、
「a:20」「b:20」と表示する。解説は以上である。

参照渡しの注意点

参照渡しの学習は終了した。ここで掲載するプログラムは、 学習の理解度を測るためのプログラムである。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//aのオブジェクトをbへ代入
007b = a ;
008
009//別のオブジェクトを設定
010a = { x : 20 } ;
011
012//それぞれ表示[a:20][b:10]
013alert ( "a:" + a.x ) ;
014alert ( "b:" + b.x ) ;
015
016//変数aのオブジェクトを変更
017a.x = 50 ;
018
019//それぞれ表示[a:50][b:10]
020alert ( "a:" + a.x ) ;
021alert ( "b:" + b.x ) ;
022</script>
プログラムを実行すると、

「a:20」
「b:10」

「a:50」
「b:10」

と表示する

では、プログラムを分割して解説する。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-2 { x : 5 }

3行目と4行目を実行すると、オブジェクトが2つ生成され、 それぞれの参照が、変数aとbへ代入される。

001<script>
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//aのオブジェクトをbへ代入
007b = a ;

7行目で変数aの参照を変数bへ代入する(参照渡し)。

変数 参照(例示) オブジェクト
a 参照-1 { x : 10 }
b 参照-1

変数aの参照が変数bへ代入される。変数aとbは、同じオブジェクトを参照する。

007b = a ;
008
009//別のオブジェクトを設定
010a = { x : 20 } ;
011
012//それぞれ表示[a:20][b:10]
013alert ( "a:" + a.x ) ;
014alert ( "b:" + b.x ) ;

7行目で参照渡しをした後、10行目で新しいオブジェクトを変数aへ代入する。

変数 参照(例示) オブジェクト
a 参照-XXX { x : 20 }
b 参照-1 { x : 10 }

10行目で新しいオブジェクトを生成し、そのオブジェクトの参照を変数aへ代入する。 表では、オブジェクトの参照を「参照-XXX」と表記した。 何度もいうが、実際の参照の値は分からない。「参照-XXX」は解説用に例示した値である。
10行目で、オブジェクト { x : 20 } を生成すると、戻り値として参照が戻る (表では「参照-XXX」)。 その参照を変数aで受け取る。
13行目と14行目で、変数aとbが参照するオブジェクトのxプロパティの値を表示する。
「a:20」「b:10」と表示する。

013alert ( "a:" + a.x ) ;
014alert ( "b:" + b.x ) ;
015
016//変数aのオブジェクトを変更
017a.x = 50 ;
018
019//それぞれ表示[a:50][b:10]
020alert ( "a:" + a.x ) ;
021alert ( "b:" + b.x ) ;

17行目で、変数aが参照するオブジェクトのxプロパティの値を「50」に変更する。

変数 参照(例示) オブジェクト
a 参照-XXX { x : 50 }
b 参照-1 { x : 10 }

変数aとbが参照するオブジェクトは異なる。今回、変数aが参照するオブジェクトの xプロパティの値を「50」にした。当然、変数bが参照するオブジェクトに影響は無い。 20行目と21行目で変数aとbが参照するオブジェクトのxプロパティの値を表示する。
「a:50」「b:10」と表示して、プログラムが終了する。

まとめ

値渡し
値をコピーして渡す。
参照
オブジェクトへの参照。 オブジェクトを参照するためのアドレスである。
参照する
変数にオブジェクトの参照が入っている場合、 「変数が参照するオブジェクト」と表現する。
参照渡し
オブジェクトの参照をコピーして、別の変数へ代入する事