回答編集履歴
4
少々言葉尻を変えたり、例え入れたりした。
test
CHANGED
@@ -84,7 +84,7 @@
|
|
84
84
|
|
85
85
|
配列やオブジェクトではそもそも参照している段階が違うと言いますか、
|
86
86
|
|
87
|
-
プリミティブなものとは、参照
|
87
|
+
プリミティブなものとは、参照している値が違うからです。
|
88
88
|
|
89
89
|
※今回の質問は配列ですが、オブジェクトの方が説明がしやすいので、オブジェクトで解説していきます。
|
90
90
|
|
@@ -124,7 +124,11 @@
|
|
124
124
|
|
125
125
|
|
126
126
|
|
127
|
+
つまり、変数に、オブジェクト変数を代入すると、
|
128
|
+
|
129
|
+
その代入先は、代入元のオブジェクト自体の参照となります。
|
130
|
+
|
127
|
-
|
131
|
+
そして、そのオブジェクトのプロパティに値を代入し直すと、
|
128
132
|
|
129
133
|
そのプロパティ自体の値の参照が置き換わるが、
|
130
134
|
|
@@ -132,9 +136,21 @@
|
|
132
136
|
|
133
137
|
a、b自体はなんら変わるわけではないわけです。
|
134
138
|
|
135
|
-
|
139
|
+
a、bは同じオブジェクトを参照しているため、bの方でプロパティの値参照を変えようと、aの方で変えようと、
|
136
140
|
|
141
|
+
同じオブジェクトを参照しているため、プロパティは共通の値となるのです。
|
142
|
+
|
143
|
+
|
144
|
+
|
137
|
-
|
145
|
+
例えば、一つのコップをAさんBさんが同時に手にもっているとします。
|
146
|
+
|
147
|
+
コップには水が入っています。
|
148
|
+
|
149
|
+
Bさんが、コップの水を捨て、お茶に置き換えれば、コップの中身は変わっても
|
150
|
+
|
151
|
+
コップ自体は変わらないのと同じです。
|
152
|
+
|
153
|
+
(二人の人間が手に持ちながら、中身を入れ直す絵面は、想像すると微妙ですが)
|
138
154
|
|
139
155
|
|
140
156
|
|
3
配列のインデックスが間違っていたため修正※他軽微な修正
test
CHANGED
@@ -66,7 +66,7 @@
|
|
66
66
|
|
67
67
|
let b = a; // 変数bは、値10への参照になる。aもbも10という値を参照している状態
|
68
68
|
|
69
|
-
b = 100; // 値100が新たに生成され、bはその値への参照となる。
|
69
|
+
b = 100; // 値100が新たに生成され、bはその値への参照となる。aとは独立している(aは値10への参照を失わない)
|
70
70
|
|
71
71
|
console.log(a); // 10
|
72
72
|
|
@@ -156,7 +156,7 @@
|
|
156
156
|
|
157
157
|
console.log(a[0]); // ひこざぶろう
|
158
158
|
|
159
|
-
console.log(b[
|
159
|
+
console.log(b[0]); // ひこざぶろう
|
160
160
|
|
161
161
|
```
|
162
162
|
|
2
指摘を受け、全面的に修正
test
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
本質問は、
|
1
|
+
本質問は、JavaScriptにおける、値の扱いの仕様、
|
2
2
|
|
3
|
-
ただし、JavaScriptにおいては、仕様が違うため、
|
4
|
-
|
5
|
-
|
3
|
+
**値の参照の置き換え**が関係していきます。
|
6
4
|
|
7
5
|
|
8
6
|
|
@@ -18,17 +16,25 @@
|
|
18
16
|
|
19
17
|
|
20
18
|
|
21
|
-
記事の通り、JavaScriptでは、**値の参照の置き換え**と言うのが表現として正しいように思いますが、
|
22
|
-
|
23
|
-
|
19
|
+
まず、プリミティブな値(数値や文字列など)が基本とすると理解できる、かと思いますので、その解説から。
|
24
|
-
|
25
|
-
(後半で、JavaScriptは値渡し、参照渡しとは言えない旨も説明します)
|
26
20
|
|
27
21
|
|
28
22
|
|
29
|
-
|
23
|
+
```javascript
|
30
24
|
|
25
|
+
let a = 10; // 値10が生成され、aは、10という値への参照となる。
|
26
|
+
|
27
|
+
console.log(a) // 10
|
28
|
+
|
29
|
+
```
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
基本、変数は、メモリに格納された値の参照であり、**変数自体には値が入っていない**ということです。
|
34
|
+
|
35
|
+
|
36
|
+
|
31
|
-
|
37
|
+
では、変数に変数を代入した時はどうなるかというと、
|
32
38
|
|
33
39
|
|
34
40
|
|
@@ -36,87 +42,21 @@
|
|
36
42
|
|
37
43
|
let a = 10;
|
38
44
|
|
39
|
-
let b = a;
|
45
|
+
let b = a; // 変数bは、値10への参照になる。aもbも10という値を"参照"している状態
|
40
|
-
|
41
|
-
b = 25;
|
42
46
|
|
43
47
|
console.log(a) // 10
|
44
48
|
|
45
|
-
console.log(b) //
|
49
|
+
console.log(b) // 10
|
46
50
|
|
47
51
|
```
|
48
52
|
|
49
53
|
|
50
54
|
|
51
|
-
|
55
|
+
となります。
|
52
56
|
|
53
|
-
プリミティブな値の
|
57
|
+
ですが、プリミティブな値の場合、bを変更しても、a自体はなんら変化がありません。
|
54
58
|
|
55
|
-
bを代入し直したとしても、aの値にはなんら影響がありません。
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
しかし、オブジェクトのプロパティの場合は異なってきます。
|
60
|
-
|
61
|
-
```javascript
|
62
|
-
|
63
|
-
const a = { key: 25, value: 15};
|
64
|
-
|
65
|
-
|
59
|
+
それはなぜかというと、
|
66
|
-
|
67
|
-
b.value = 35;
|
68
|
-
|
69
|
-
console.log(a.value) // 35
|
70
|
-
|
71
|
-
console.log(b.value) // 35
|
72
|
-
|
73
|
-
```
|
74
|
-
|
75
|
-
これは、bにaを代入した際、bはaへの参照を代入されただけであって、
|
76
|
-
|
77
|
-
bとaは不可分の関係となるため、bの値を変更すると、aの値も変わってしまうわけです。
|
78
|
-
|
79
|
-
これが、**参照渡し**となります。
|
80
|
-
|
81
|
-
JavaScriptにおいては、オブジェクト、配列などが、代入の際、参照渡しとなるため、
|
82
|
-
|
83
|
-
今回の質問のように、**代入先の変数の値を変更すると、
|
84
|
-
|
85
|
-
元の変数の値も変更されてしまう**のです。
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
動きというか、見た目の挙動の話は以上です。
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
ここからは、参考記事にもある通り、
|
96
|
-
|
97
|
-
JavaScriptは、**値渡し**、**参照渡し**とは言えない所以を解説していきます。
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
まず、値渡しとは、変数に値自体が格納されている、代入の際も値自体を渡しているので言えることなのですが、
|
102
|
-
|
103
|
-
JavaScriptは仕様が違っており、
|
104
|
-
|
105
|
-
**変数自体に値が入ることがそもそもありません**。
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
```javascript
|
110
|
-
|
111
|
-
let a = 10; // この時点で、値10が生成され、aには、10という値への参照が渡される
|
112
|
-
|
113
|
-
```
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
となり、もともとが**値への参照渡し**となります。
|
118
|
-
|
119
|
-
そして、変数から変数にプリミティブな値を代入した際どうなるかというと、
|
120
60
|
|
121
61
|
|
122
62
|
|
@@ -124,31 +64,9 @@
|
|
124
64
|
|
125
65
|
let a = 10;
|
126
66
|
|
127
|
-
let b = a; // 値10への参照
|
67
|
+
let b = a; // 変数bは、値10への参照になる。aもbも10という値を参照している状態
|
128
68
|
|
129
|
-
```
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
となります。
|
134
|
-
|
135
|
-
つまりC#でいう**参照渡し状態**と言えます。
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
ではなぜ、プリミティブな値の場合、aとbは独立するのか。
|
140
|
-
|
141
|
-
それは下記のような状態になるからです。
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
```javascript
|
146
|
-
|
147
|
-
let a = 10;
|
148
|
-
|
149
|
-
let b = a; // 値10への参照が渡されるため、aもbも同じ値を"参照"している状態
|
150
|
-
|
151
|
-
b = 100; // 値100が新たに生成され、その値への参照
|
69
|
+
b = 100; // 値100が新たに生成され、bはその値への参照となる。この時点で、aとは独立する(aは値10への参照を失わない)
|
152
70
|
|
153
71
|
console.log(a); // 10
|
154
72
|
|
@@ -158,54 +76,100 @@
|
|
158
76
|
|
159
77
|
|
160
78
|
|
161
|
-
ということが起きるからです。
|
162
|
-
|
163
|
-
|
79
|
+
となり、ようは、**参照の置き換え**が発生します。
|
164
80
|
|
165
81
|
|
166
82
|
|
167
|
-
では、
|
83
|
+
では、本質問のようなことがなぜ起こるのか。
|
84
|
+
|
85
|
+
配列やオブジェクトではそもそも参照している段階が違うと言いますか、
|
86
|
+
|
87
|
+
プリミティブなものとは、参照の段階が違うからです。
|
88
|
+
|
89
|
+
※今回の質問は配列ですが、オブジェクトの方が説明がしやすいので、オブジェクトで解説していきます。
|
168
90
|
|
169
91
|
|
170
92
|
|
171
93
|
```javascript
|
172
94
|
|
173
|
-
const a = { val: 10 };
|
174
|
-
|
175
|
-
const b = a;
|
176
|
-
|
177
|
-
a.val = 100;
|
178
|
-
|
179
|
-
cons
|
95
|
+
const a = {key: 0, value: 15}; // aは{}の参照となる。そして、各プロパティは、各値の参照となる
|
180
96
|
|
181
97
|
```
|
182
98
|
|
99
|
+
|
100
|
+
|
101
|
+
という状態になり、a自体は、{}というオブジェクト自体の参照となります。
|
102
|
+
|
183
|
-
|
103
|
+
そして、各プロパティは、各値の参照となります。
|
104
|
+
|
105
|
+
よって、このオブジェクト参照の変数を、他の変数に代入するとどうなるか。
|
184
106
|
|
185
107
|
|
186
108
|
|
109
|
+
```javascript
|
110
|
+
|
111
|
+
const a = {key: 0, value: 15}; // aは{}の参照となる。そして、各プロパティは、各値の参照となる
|
112
|
+
|
113
|
+
const b = a; // bは{key,value}というオブジェクト自体の参照となる
|
114
|
+
|
187
|
-
|
115
|
+
b.value = 35; // {key,value}というオブジェクトの、valueの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
|
116
|
+
|
117
|
+
// よって、下記のような結果となる
|
118
|
+
|
119
|
+
console.log(a.value); // 35
|
120
|
+
|
121
|
+
console.log(b.value); // 35
|
122
|
+
|
123
|
+
```
|
188
124
|
|
189
125
|
|
190
126
|
|
127
|
+
つまり、オブジェクトのプロパティに代入し直すと、
|
128
|
+
|
129
|
+
そのプロパティ自体の値の参照が置き換わるが、
|
130
|
+
|
131
|
+
オブジェクト自体への参照が置き換わるわけではないため、
|
132
|
+
|
133
|
+
a、b自体はなんら変わるわけではないわけです。
|
134
|
+
|
191
|
-
|
135
|
+
(注意が必要なのは、同じ、`{key, value}`というオブジェクトを参照しているため。一見、aとbは不可分に見えるが、本質的には、代入した時点でaとbは独立している。)
|
136
|
+
|
137
|
+
各プロパティの出力値が同じになるのはこういうことになります。
|
192
138
|
|
193
139
|
|
194
140
|
|
195
|
-
と
|
141
|
+
これは、配列においても同じことがいえます。
|
196
142
|
|
197
|
-
|
143
|
+
(というかJavaScriptにおいては配列もオブジェクト)
|
198
|
-
|
199
|
-
JavaScriptは他の言語とは違う面をみたり、実際に挙動を確認した限りでは、
|
200
|
-
|
201
|
-
今回参考に挙げた記事が正しいのではないかな、と思います。
|
202
144
|
|
203
145
|
|
204
146
|
|
147
|
+
```javascript
|
148
|
+
|
149
|
+
const a = ['まさひこ', 'たかひこ']; // aは[0, 1]の参照となる。そして、要素(インデックス)は、各値の参照となる
|
150
|
+
|
205
|
-
|
151
|
+
const b = a; // bは[0, 1]という配列自体の参照となる
|
152
|
+
|
153
|
+
b[0] = 'ひこざぶろう'; // [0, 1]という配列の、0インデックスの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
|
154
|
+
|
155
|
+
// よって、下記のような結果となる
|
156
|
+
|
157
|
+
console.log(a[0]); // ひこざぶろう
|
158
|
+
|
159
|
+
console.log(b[1]); // ひこざぶろう
|
160
|
+
|
161
|
+
```
|
206
162
|
|
207
163
|
|
208
164
|
|
209
|
-
|
165
|
+
よって、今回の配列のような参照元の配列の値の参照が置き換わるので、今回の質問のような結果となります。
|
210
166
|
|
167
|
+
|
168
|
+
|
169
|
+
前回答状態では、誤解と、間違った回答となっていたため、
|
170
|
+
|
171
|
+
大変に失礼しました。
|
172
|
+
|
173
|
+
|
174
|
+
|
211
|
-
間違ってい
|
175
|
+
また、間違っている部分があれば、ご指摘いただければ幸いです。
|
1
JavaScriptがなぜこのような仕様になったかの解説を少々追加
test
CHANGED
@@ -80,9 +80,9 @@
|
|
80
80
|
|
81
81
|
JavaScriptにおいては、オブジェクト、配列などが、代入の際、参照渡しとなるため、
|
82
82
|
|
83
|
-
今回の質問のように、代入先の変数の値を変更すると、
|
83
|
+
今回の質問のように、**代入先の変数の値を変更すると、
|
84
|
-
|
84
|
+
|
85
|
-
元の変数の値も変更されてしまうのです。
|
85
|
+
元の変数の値も変更されてしまう**のです。
|
86
86
|
|
87
87
|
|
88
88
|
|
@@ -150,6 +150,10 @@
|
|
150
150
|
|
151
151
|
b = 100; // 値100が新たに生成され、その値への参照がbに格納される。この時点で、aとは独立する(aは値10への参照を失わない)
|
152
152
|
|
153
|
+
console.log(a); // 10
|
154
|
+
|
155
|
+
console.log(b); // 100
|
156
|
+
|
153
157
|
```
|
154
158
|
|
155
159
|
|
@@ -198,6 +202,10 @@
|
|
198
202
|
|
199
203
|
|
200
204
|
|
205
|
+
また、もともとが、HTMLに対してアクションを起こすものから始まった関係上、このような仕様になっていったのではないかな、と思います。
|
206
|
+
|
207
|
+
|
208
|
+
|
201
209
|
長文失礼しました。
|
202
210
|
|
203
211
|
間違っていたら、どうかご指摘いただければ幸いです。
|