回答編集履歴
4
少々言葉尻を変えたり、例え入れたりした。
answer
CHANGED
@@ -41,7 +41,7 @@
|
|
41
41
|
|
42
42
|
では、本質問のようなことがなぜ起こるのか。
|
43
43
|
配列やオブジェクトではそもそも参照している段階が違うと言いますか、
|
44
|
-
プリミティブなものとは、参照
|
44
|
+
プリミティブなものとは、参照している値が違うからです。
|
45
45
|
※今回の質問は配列ですが、オブジェクトの方が説明がしやすいので、オブジェクトで解説していきます。
|
46
46
|
|
47
47
|
```javascript
|
@@ -61,13 +61,21 @@
|
|
61
61
|
console.log(b.value); // 35
|
62
62
|
```
|
63
63
|
|
64
|
+
つまり、変数に、オブジェクト変数を代入すると、
|
65
|
+
その代入先は、代入元のオブジェクト自体の参照となります。
|
64
|
-
|
66
|
+
そして、そのオブジェクトのプロパティに値を代入し直すと、
|
65
67
|
そのプロパティ自体の値の参照が置き換わるが、
|
66
68
|
オブジェクト自体への参照が置き換わるわけではないため、
|
67
69
|
a、b自体はなんら変わるわけではないわけです。
|
68
|
-
|
70
|
+
a、bは同じオブジェクトを参照しているため、bの方でプロパティの値参照を変えようと、aの方で変えようと、
|
69
|
-
|
71
|
+
同じオブジェクトを参照しているため、プロパティは共通の値となるのです。
|
70
72
|
|
73
|
+
例えば、一つのコップをAさんBさんが同時に手にもっているとします。
|
74
|
+
コップには水が入っています。
|
75
|
+
Bさんが、コップの水を捨て、お茶に置き換えれば、コップの中身は変わっても
|
76
|
+
コップ自体は変わらないのと同じです。
|
77
|
+
(二人の人間が手に持ちながら、中身を入れ直す絵面は、想像すると微妙ですが)
|
78
|
+
|
71
79
|
これは、配列においても同じことがいえます。
|
72
80
|
(というかJavaScriptにおいては配列もオブジェクト)
|
73
81
|
|
3
配列のインデックスが間違っていたため修正※他軽微な修正
answer
CHANGED
@@ -32,7 +32,7 @@
|
|
32
32
|
```javascript
|
33
33
|
let a = 10;
|
34
34
|
let b = a; // 変数bは、値10への参照になる。aもbも10という値を参照している状態
|
35
|
-
b = 100; // 値100が新たに生成され、bはその値への参照となる。
|
35
|
+
b = 100; // 値100が新たに生成され、bはその値への参照となる。aとは独立している(aは値10への参照を失わない)
|
36
36
|
console.log(a); // 10
|
37
37
|
console.log(b); // 100
|
38
38
|
```
|
@@ -77,7 +77,7 @@
|
|
77
77
|
b[0] = 'ひこざぶろう'; // [0, 1]という配列の、0インデックスの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
|
78
78
|
// よって、下記のような結果となる
|
79
79
|
console.log(a[0]); // ひこざぶろう
|
80
|
-
console.log(b[
|
80
|
+
console.log(b[0]); // ひこざぶろう
|
81
81
|
```
|
82
82
|
|
83
83
|
よって、今回の配列のような参照元の配列の値の参照が置き換わるので、今回の質問のような結果となります。
|
2
指摘を受け、全面的に修正
answer
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
本質問は、よく話に聞く、**値渡し**なのか、**参照渡し**なのか、ということが関係してきます。
|
2
|
-
|
1
|
+
本質問は、JavaScriptにおける、値の扱いの仕様、
|
3
|
-
|
2
|
+
**値の参照の置き換え**が関係していきます。
|
4
3
|
|
5
4
|
非公式でないので、正確性に欠ける可能性がありますが、
|
6
5
|
読んでいる限りは、合っていると思ったので、
|
@@ -8,99 +7,82 @@
|
|
8
7
|
|
9
8
|
[JavaScriptに参照渡し/値渡しなど存在しない - Qiita](https://qiita.com/yuta0801/items/f8690a6e129c594de5fb)
|
10
9
|
|
11
|
-
記事の通り、JavaScriptでは、**値の参照の置き換え**と言うのが表現として正しいように思いますが、
|
12
|
-
|
10
|
+
まず、プリミティブな値(数値や文字列など)が基本とすると理解できる、かと思いますので、その解説から。
|
13
|
-
(後半で、JavaScriptは値渡し、参照渡しとは言えない旨も説明します)
|
14
11
|
|
15
|
-
まず下記でよくみるのは、変数の中身が置き換わっているので、
|
16
|
-
値渡しとなるパターンです。
|
17
|
-
|
18
12
|
```javascript
|
19
|
-
let a = 10;
|
13
|
+
let a = 10; // 値10が生成され、aは、10という値への参照となる。
|
20
|
-
let b = a;
|
21
|
-
b = 25;
|
22
14
|
console.log(a) // 10
|
23
|
-
console.log(b) // 25
|
24
15
|
```
|
25
16
|
|
26
|
-
これは、たとえ、bにaを代入したとしても、
|
27
|
-
プリミティブな値のため、値渡しとなるため、
|
28
|
-
|
17
|
+
基本、変数は、メモリに格納された値の参照であり、**変数自体には値が入っていない**ということです。
|
29
18
|
|
30
|
-
|
19
|
+
では、変数に変数を代入した時はどうなるかというと、
|
20
|
+
|
31
21
|
```javascript
|
32
|
-
const a = { key: 25, value: 15};
|
33
|
-
|
22
|
+
let a = 10;
|
34
|
-
b
|
23
|
+
let b = a; // 変数bは、値10への参照になる。aもbも10という値を"参照"している状態
|
35
|
-
console.log(a
|
24
|
+
console.log(a) // 10
|
36
|
-
console.log(b
|
25
|
+
console.log(b) // 10
|
37
26
|
```
|
38
|
-
これは、bにaを代入した際、bはaへの参照を代入されただけであって、
|
39
|
-
bとaは不可分の関係となるため、bの値を変更すると、aの値も変わってしまうわけです。
|
40
|
-
これが、**参照渡し**となります。
|
41
|
-
JavaScriptにおいては、オブジェクト、配列などが、代入の際、参照渡しとなるため、
|
42
|
-
今回の質問のように、**代入先の変数の値を変更すると、
|
43
|
-
元の変数の値も変更されてしまう**のです。
|
44
27
|
|
28
|
+
となります。
|
45
|
-
|
29
|
+
ですが、プリミティブな値の場合、bを変更しても、a自体はなんら変化がありません。
|
30
|
+
それはなぜかというと、
|
46
31
|
|
47
|
-
|
48
|
-
ここからは、参考記事にもある通り、
|
49
|
-
JavaScriptは、**値渡し**、**参照渡し**とは言えない所以を解説していきます。
|
50
|
-
|
51
|
-
まず、値渡しとは、変数に値自体が格納されている、代入の際も値自体を渡しているので言えることなのですが、
|
52
|
-
JavaScriptは仕様が違っており、
|
53
|
-
**変数自体に値が入ることがそもそもありません**。
|
54
|
-
|
55
32
|
```javascript
|
33
|
+
let a = 10;
|
56
|
-
let
|
34
|
+
let b = a; // 変数bは、値10への参照になる。aもbも10という値を参照している状態
|
35
|
+
b = 100; // 値100が新たに生成され、bはその値への参照となる。この時点で、aとは独立する(aは値10への参照を失わない)
|
36
|
+
console.log(a); // 10
|
37
|
+
console.log(b); // 100
|
57
38
|
```
|
58
39
|
|
59
|
-
となり、
|
40
|
+
となり、ようは、**参照の置き換え**が発生します。
|
60
|
-
そして、変数から変数にプリミティブな値を代入した際どうなるかというと、
|
61
41
|
|
42
|
+
では、本質問のようなことがなぜ起こるのか。
|
43
|
+
配列やオブジェクトではそもそも参照している段階が違うと言いますか、
|
44
|
+
プリミティブなものとは、参照の段階が違うからです。
|
45
|
+
※今回の質問は配列ですが、オブジェクトの方が説明がしやすいので、オブジェクトで解説していきます。
|
46
|
+
|
62
47
|
```javascript
|
63
|
-
let a = 10;
|
64
|
-
|
48
|
+
const a = {key: 0, value: 15}; // aは{}の参照となる。そして、各プロパティは、各値の参照となる
|
65
49
|
```
|
66
50
|
|
67
|
-
となります。
|
51
|
+
という状態になり、a自体は、{}というオブジェクト自体の参照となります。
|
68
|
-
|
52
|
+
そして、各プロパティは、各値の参照となります。
|
53
|
+
よって、このオブジェクト参照の変数を、他の変数に代入するとどうなるか。
|
69
54
|
|
70
|
-
ではなぜ、プリミティブな値の場合、aとbは独立するのか。
|
71
|
-
それは下記のような状態になるからです。
|
72
|
-
|
73
55
|
```javascript
|
74
|
-
|
56
|
+
const a = {key: 0, value: 15}; // aは{}の参照となる。そして、各プロパティは、各値の参照となる
|
75
|
-
|
57
|
+
const b = a; // bは{key,value}というオブジェクト自体の参照となる
|
76
|
-
b =
|
58
|
+
b.value = 35; // {key,value}というオブジェクトの、valueの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
|
59
|
+
// よって、下記のような結果となる
|
77
|
-
console.log(a); //
|
60
|
+
console.log(a.value); // 35
|
78
|
-
console.log(b); //
|
61
|
+
console.log(b.value); // 35
|
79
62
|
```
|
80
63
|
|
64
|
+
つまり、オブジェクトのプロパティに代入し直すと、
|
65
|
+
そのプロパティ自体の値の参照が置き換わるが、
|
66
|
+
オブジェクト自体への参照が置き換わるわけではないため、
|
81
|
-
|
67
|
+
a、b自体はなんら変わるわけではないわけです。
|
68
|
+
(注意が必要なのは、同じ、`{key, value}`というオブジェクトを参照しているため。一見、aとbは不可分に見えるが、本質的には、代入した時点でaとbは独立している。)
|
82
|
-
|
69
|
+
各プロパティの出力値が同じになるのはこういうことになります。
|
83
70
|
|
84
|
-
|
71
|
+
これは、配列においても同じことがいえます。
|
72
|
+
(というかJavaScriptにおいては配列もオブジェクト)
|
85
73
|
|
86
74
|
```javascript
|
75
|
+
const a = ['まさひこ', 'たかひこ']; // aは[0, 1]の参照となる。そして、要素(インデックス)は、各値の参照となる
|
87
|
-
const
|
76
|
+
const b = a; // bは[0, 1]という配列自体の参照となる
|
77
|
+
b[0] = 'ひこざぶろう'; // [0, 1]という配列の、0インデックスの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
|
78
|
+
// よって、下記のような結果となる
|
88
|
-
|
79
|
+
console.log(a[0]); // ひこざぶろう
|
89
|
-
a.val = 100;
|
90
|
-
console.log(b); //
|
80
|
+
console.log(b[1]); // ひこざぶろう
|
91
81
|
```
|
92
|
-
これはすみません、記事をそのまま引用させていただきます。
|
93
82
|
|
94
|
-
|
83
|
+
よって、今回の配列のような参照元の配列の値の参照が置き換わるので、今回の質問のような結果となります。
|
95
84
|
|
96
|
-
|
85
|
+
前回答状態では、誤解と、間違った回答となっていたため、
|
86
|
+
大変に失礼しました。
|
97
87
|
|
98
|
-
となります。
|
99
|
-
私自身、ECMAScriptの仕様書を読んだわけでは無いのですが、
|
100
|
-
JavaScriptは他の言語とは違う面をみたり、実際に挙動を確認した限りでは、
|
101
|
-
今回参考に挙げた記事が正しいのではないかな、と思います。
|
102
|
-
|
103
|
-
また、もともとが、HTMLに対してアクションを起こすものから始まった関係上、このような仕様になっていったのではないかな、と思います。
|
104
|
-
|
105
|
-
長文失礼しました。
|
106
|
-
間違ってい
|
88
|
+
また、間違っている部分があれば、ご指摘いただければ幸いです。
|
1
JavaScriptがなぜこのような仕様になったかの解説を少々追加
answer
CHANGED
@@ -39,8 +39,8 @@
|
|
39
39
|
bとaは不可分の関係となるため、bの値を変更すると、aの値も変わってしまうわけです。
|
40
40
|
これが、**参照渡し**となります。
|
41
41
|
JavaScriptにおいては、オブジェクト、配列などが、代入の際、参照渡しとなるため、
|
42
|
-
今回の質問のように、代入先の変数の値を変更すると、
|
42
|
+
今回の質問のように、**代入先の変数の値を変更すると、
|
43
|
-
元の変数の値も変更されてしまうのです。
|
43
|
+
元の変数の値も変更されてしまう**のです。
|
44
44
|
|
45
45
|
動きというか、見た目の挙動の話は以上です。
|
46
46
|
|
@@ -74,6 +74,8 @@
|
|
74
74
|
let a = 10;
|
75
75
|
let b = a; // 値10への参照が渡されるため、aもbも同じ値を"参照"している状態
|
76
76
|
b = 100; // 値100が新たに生成され、その値への参照がbに格納される。この時点で、aとは独立する(aは値10への参照を失わない)
|
77
|
+
console.log(a); // 10
|
78
|
+
console.log(b); // 100
|
77
79
|
```
|
78
80
|
|
79
81
|
ということが起きるからです。
|
@@ -98,5 +100,7 @@
|
|
98
100
|
JavaScriptは他の言語とは違う面をみたり、実際に挙動を確認した限りでは、
|
99
101
|
今回参考に挙げた記事が正しいのではないかな、と思います。
|
100
102
|
|
103
|
+
また、もともとが、HTMLに対してアクションを起こすものから始まった関係上、このような仕様になっていったのではないかな、と思います。
|
104
|
+
|
101
105
|
長文失礼しました。
|
102
106
|
間違っていたら、どうかご指摘いただければ幸いです。
|