【JavaScript 中級講座】値渡しと参照渡し
本講座では、値渡しと参照渡しについて学習する。
値渡しも参照渡しも、多くのプログラミング言語に関係する、非常に重要な概念である。
本講座はJavaScriptの勉強というより、
プログラミングの基礎的内容をJavaScriptで学習する、という意味合いが強い。
値渡し
まず、値渡しから学習する。簡単な内容であるが、集中して学習してほしい。
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
と表示する。
長いプログラムなので、分割して解説する。
002//変数を宣言
003var a = 10 ;
004var b = 5 ;
3行目と4行目で変数a、bを宣言して、それぞれ「10」と「5」を代入する。 この時コンピューター上には、変数が2つ作成される。
変数 | 値 |
a | 10 |
b | 5 |
このような状態である。簡単である。最初は簡単である。今後この表が複雑になる。
004var b = 5 ;
005
006//それぞれ表示[a:10][b:5]
007alert ( "a:" + a ) ;
008alert ( "b:" + b ) ;
7行目と8行目で、変数の値をそれぞれ表示する。
「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 |
コンピューターは、このようになる。
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の値は変更されない。 「当たり前」と思う方もいらっしゃるだろうが、「参照渡し」の学習で最も重要な話になるので、 覚えてほしい。
019
020//それぞれ表示[a:20][b:10]
021alert ( "a:" + a ) ;
022alert ( "b:" + b ) ;
023</script>
プログラムの最後で、変数aとbの値を表示する。 「a:20」「b:10」と表示してプログラムが終了する。 以上が値渡しである。
オブジェクトを作成して変数へ代入する
参照渡しの解説をする前に、 「オブジェクトを変数へ代入する」という意味を正確に解説する。
002//オブジェクトを作成
003var a = { x : 10 } ;
004</script>
3行目を詳しく見る。まず、「 = 」の右側でオブジェクトが生成される。 コンピューター上にオブジェクトが作られる。
オブジェクト |
{ x : 10 } |
これが、オブジェクトを生成するという意味である。 さて、オブジェクトを生成すると、戻り値として「参照」が戻る。
参照とは、オブジェクトを参照するための値である。 実際はオブジェクトが存在するアドレス値である。 しかし参照の値を、プログラマーが意識する必要は全く無い。 「オブジェクトを生成すると、オブジェクトを参照するための参照が戻る」 という事実のみ意識する必要がある。
参照とはアドレスである。これが事実である。
しかし、アドレスと言ってもイメージする事が難しい。
「参照はオブジェクトの名前」とイメージすると良い。
オブジェクトを生成すると、コンピューター上にオブジェクトができる。
コンピューター上にオブジェクトができるのは良いが、名前がなければ利用できない。
そこで、オブジェクトに名前を付ける。それが参照である(というイメージである)。
オブジェクトを生成すると、オブジェクトの名前(参照)が戻される。
002//オブジェクトを作成
003var a = { x : 10 } ;
004</script>
3行目で変数aを宣言して、オブジェクトの参照を受け取っている。
変数 | 参照(例示) | オブジェクト |
a | 参照-1 | { x : 10 } |
この表は重要である。
解説する。まず、変数aには参照「参照-1」が入っている。
この参照はオブジェクトの名前である。
オブジェクトを利用する場合、この参照(名前)を利用する。
通常、参照の値を意識する必要は無い。しかし、「参照渡し」を学習する際、
「参照-1」のように、具体的な値を例示したほうが理解が進む。
ちなみに、「参照-1」は解説用の参照の例であって、実際の値とは異なる。
注意してほしい。実際の参照の値は分からない。
さて、参照「参照-1」が参照しているオブジェクトは
{ x : 10 }である。
オブジェクト{ x : 10 }を利用するためには、
この参照「参照-1」(「オブジェクトの名前」というイメージ)が必要である。
解説は以上である。
メモリ上にオブジェクトを展開
オブジェクトの存在がもっと身近になるように、サンプルを見る。 (まだ、参照渡しの学習に入っていない。参照渡しを理解するための準備段階である)
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が参照するオブジェクトは同じ構造を持っている。
しかし、実際は二つのオブジェクトが生成され、コンピューター上に存在する。
メモリ上のオブジェクトを理解する
参照渡しを理解するための準備をする。
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>
プログラムを解説する。3行目で変数aを宣言してオブジェクトを代入する。 4行目で変数bを宣言してオブジェクトを代入する。 「オブジェクトを代入」と解説したが、実際はオブジェクトの参照を 変数a、bへ代入する。
変数 | 参照(例示) | オブジェクト |
a | 参照-1 | { x : 10 } |
b | 参照-2 | { x : 10 } |
3行目と4行目が終了した時点で、コンピューター上に二つのオブジェクトが存在する。
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が参照するオブジェクトに影響しない。
009alert ( "a:" + a.x ) ;
010alert ( "b:" + b.x ) ;
011</script>
9行目と10行目で変数a、bが参照するオブジェクトのxプロパティの値を表示する。 プログラムを実行すると、「a:20」「b:10」と表示する。
参照渡しを実行する
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 }
は、どこかへ消える。
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
005
006//参照渡し
007b = a ;
008</script>
7行目を実行すると、変数aと変数bは同じオブジェクトを参照する。
参照渡しの動作確認
参照渡しの動作をまとめたサンプルプログラムを掲載する。
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」
と表示する。
参照渡しの動作を確認するプログラムである。 プログラムを分割しながら解説する。
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」と表示する。
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は、同じオブジェクトを参照する。
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」と表示する。
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」と表示する。解説は以上である。
参照渡しの注意点
参照渡しの学習は終了した。ここで掲載するプログラムは、 学習の理解度を測るためのプログラムである。
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」
と表示する
では、プログラムを分割して解説する。
002//オブジェクトを作成
003var a = { x : 10 } ;
004var b = { x : 5 } ;
変数 | 参照(例示) | オブジェクト |
a | 参照-1 | { x : 10 } |
b | 参照-2 | { x : 5 } |
3行目と4行目を実行すると、オブジェクトが2つ生成され、 それぞれの参照が、変数aとbへ代入される。
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は、同じオブジェクトを参照する。
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」と表示する。
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」と表示して、プログラムが終了する。