回答編集履歴

4

少々言葉尻を変えたり、例え入れたりした。

2019/10/28 01:43

投稿

miyabi_pudding
miyabi_pudding

スコア9528

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
- (注意が必要なの同じ、`{key, value}`というオブジェクトを参照しているため。一見aとbは不可分に見るが本質的には、代入した時点abは独立している。)
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

配列のインデックスが間違っていたため修正※他軽微な修正

2019/10/28 01:43

投稿

miyabi_pudding
miyabi_pudding

スコア9528

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はその値への参照となる。この時点で、aとは独立る(aは値10への参照を失わない)
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[1]); // ひこざぶろう
159
+ console.log(b[0]); // ひこざぶろう
160
160
 
161
161
  ```
162
162
 

2

指摘を受け、全面的に修正

2019/10/28 01:14

投稿

miyabi_pudding
miyabi_pudding

スコア9528

test CHANGED
@@ -1,8 +1,6 @@
1
- 本質問は、よく話聞く**渡し**なか、**参照渡し**なということが関係してきます。
1
+ 本質問は、JavaScriptおける、値の扱い仕様
2
2
 
3
- ただし、JavaScriptにおいては、仕様が違うため、
4
-
5
- C#で言う、**値渡し**、**参照渡し**、の**ようなもの**のようです。
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) // 25
49
+ console.log(b) // 10
46
50
 
47
51
  ```
48
52
 
49
53
 
50
54
 
51
- これは、たえ、bにaを代入したとしても、
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
- const b = a;
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への参照が渡されため、aもbも同じ値を"参照"している状態
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が新たに生成され、その値への参照がbに格納される。この時点で、aとは独立する(aは値10への参照を失わない)
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
- console.log(b); // { val: 100 }
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
- > 代入してる対象は変数自体ではなく、その変数が持っている(参照の先にある)オブジェクトのプロパティです。つまり「変数にを再代入すると"値の参照"が置き換わる」が当てはまらず、2つ変数が同じオブジェクトを指しているままになりただ同じオブジェクトを操作してるだけになります。(プリミティブ値はプロパティ代入できないで逆のこときないのですが)
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
- 私自身、ECMAScriptの仕様書を読んだわけで無いのですが、
143
+ (というかJavaScriptにおいて配列もオブジェクト)
198
-
199
- JavaScriptは他の言語とは違う面をみたり、実際に挙動を確認した限りでは、
200
-
201
- 今回参考に挙げた記事が正しいのではないかな、と思います。
202
144
 
203
145
 
204
146
 
147
+ ```javascript
148
+
149
+ const a = ['まさひこ', 'たかひこ']; // aは[0, 1]の参照となる。そして、要素(インデックス)は、各値の参照となる
150
+
205
- また、ももとが、HTMLに対してアクションを起こすものから始まった関係上、このよな仕様になっていったではいかな、と思います。
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がなぜこのような仕様になったかの解説を少々追加

2019/10/28 01:07

投稿

miyabi_pudding
miyabi_pudding

スコア9528

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
  間違っていたら、どうかご指摘いただければ幸いです。