teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

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

2019/10/28 01:43

投稿

miyabi_pudding
miyabi_pudding

スコア9567

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
- (注意が必要なのは、同じ、`{key, value}`というオブジェクトを参照しているため。一見aとbは不可分に見るが本質的には、代入した時点でaとbは独立している。)
70
+ abは同じオブジェクトを参照しているため、bの方でプロパティの値参照を変ようと、aの方で変えよう
69
- プロパティの出力が同じになるのはこういうことになります。
71
+ 同じオブジェクトを参照しているため、プロパティは共通の値なるのす。
70
72
 
73
+ 例えば、一つのコップをAさんBさんが同時に手にもっているとします。
74
+ コップには水が入っています。
75
+ Bさんが、コップの水を捨て、お茶に置き換えれば、コップの中身は変わっても
76
+ コップ自体は変わらないのと同じです。
77
+ (二人の人間が手に持ちながら、中身を入れ直す絵面は、想像すると微妙ですが)
78
+
71
79
  これは、配列においても同じことがいえます。
72
80
  (というかJavaScriptにおいては配列もオブジェクト)
73
81
 

3

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

2019/10/28 01:43

投稿

miyabi_pudding
miyabi_pudding

スコア9567

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はその値への参照となる。この時点で、aとは独立る(aは値10への参照を失わない)
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[1]); // ひこざぶろう
80
+ console.log(b[0]); // ひこざぶろう
81
81
  ```
82
82
 
83
83
  よって、今回の配列のような参照元の配列の値の参照が置き換わるので、今回の質問のような結果となります。

2

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

2019/10/28 01:14

投稿

miyabi_pudding
miyabi_pudding

スコア9567

answer CHANGED
@@ -1,6 +1,5 @@
1
- 本質問は、よく話に聞く、**値渡し**なのか、**参照渡し**なのか、ということが関係してきます。
2
- ただし、JavaScriptにおいては、仕様が違うため
1
+ 本質問は、JavaScriptにおける値の扱いの仕様、
3
- C#で言う、**値渡し**、**参照渡し**、の**ようなもの**のようです。
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
- bを代入し直したとしてもaの値にはなんら影響ありません
17
+ 基本変数は、メモリに格納されたの参照であり、**変数自体には入っていない**ということです
29
18
 
30
- しかしオブジェクトのプロパティの場合ってきます。
19
+ では変数に変数を代入した時どうるかというと、
20
+
31
21
  ```javascript
32
- const a = { key: 25, value: 15};
33
- const b = a;
22
+ let a = 10;
34
- b.value = 35;
23
+ let b = a; // 変数bは、値10への参照になる。aもbも10という値を"参照"している状態
35
- console.log(a.value) // 35
24
+ console.log(a) // 10
36
- console.log(b.value) // 35
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 a = 10; // この時点で、値10が生成され、aは、10という値への参照が渡され
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
- let b = a; // 値10への参照が渡されためaもbも同じを"参照"してい状態
48
+ const a = {key: 0, value: 15}; // aは{}の参照とな。そして各プロパティは、各参照とな
65
49
  ```
66
50
 
67
- となります。
51
+ いう状態になり、a自体は、{}というオブジェクト自体の参照となります。
68
- つまりC#でいう**参照渡し状態**言えます。
52
+ そして、各プロパティは、各値の参照となります。
53
+ よって、このオブジェクト参照の変数を、他の変数に代入するとどうなるか。
69
54
 
70
- ではなぜ、プリミティブな値の場合、aとbは独立するのか。
71
- それは下記のような状態になるからです。
72
-
73
55
  ```javascript
74
- let a = 10;
56
+ const a = {key: 0, value: 15}; // aは{}の参照となる。そして、各プロパティは、各値の参照となる
75
- let b = a; // 値10への参照が渡されため、aもbも同じ値を"参照"している状態
57
+ const b = a; // bは{key,value}というオブジェクト自体の参照とな
76
- b = 100; // 値100が新たに生成されの値の参照がbに格納される。時点で、aとは独立する(aは値10への参照を失わない
58
+ b.value = 35; // {key,value}というオブジェクトのvalueの値の参照が置き換わる。ため、a、b自体の参照は置き換ない
59
+ // よって、下記のような結果となる
77
- console.log(a); // 10
60
+ console.log(a.value); // 35
78
- console.log(b); // 100
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 a = { val: 10 };
76
+ const b = a; // bは[0, 1]という配列自体の参照となる
77
+ b[0] = 'ひこざぶろう'; // [0, 1]という配列の、0インデックスの値の参照が置き換わる。そのため、a、b自体の参照は置き換わらない
78
+ // よって、下記のような結果となる
88
- const b = a;
79
+ console.log(a[0]); // ひこざぶろう
89
- a.val = 100;
90
- console.log(b); // { val: 100 }
80
+ console.log(b[1]); // ひこざぶろう
91
81
  ```
92
- これはすみません、記事をそのまま引用させていただきます。
93
82
 
94
- > 代入しいる対象は変数自体ではなく変数が持っている(参照の先にある)オブジェクトプロパティです。つまり、「変数にを再代入すると"値の参照"が置き換わる」が当てはまらず2つ変数が同じオブジェクトを指しているままにり、ただ同じオブジェクトを操作してるだけになります。(プリミティブ値はプロパティ代入できないので逆のことはできないのですが)
83
+ よって、今回配列のような参照配列の値の参照が置き換わるので今回質問のよう結果となります。
95
84
 
96
- > それから変数自体に値を代入すれば「変数に値を再代入する"値の参照"が置き換わる」が当はまるのでもちろん値は変わりません。
85
+ 前回答状態では、誤解、間違った回答となっいたため
86
+ 大変に失礼しました。
97
87
 
98
- となります。
99
- 私自身、ECMAScriptの仕様書を読んだわけでは無いのですが、
100
- JavaScriptは他の言語とは違う面をみたり、実際に挙動を確認した限りでは、
101
- 今回参考に挙げた記事が正しいのではないかな、と思います。
102
-
103
- また、もともとが、HTMLに対してアクションを起こすものから始まった関係上、このような仕様になっていったのではないかな、と思います。
104
-
105
- 長文失礼しました。
106
- 間違っていたらどうかご指摘いただければ幸いです。
88
+ また、間違っている部分があれば、ご指摘いただければ幸いです。

1

JavaScriptがなぜこのような仕様になったかの解説を少々追加

2019/10/28 01:07

投稿

miyabi_pudding
miyabi_pudding

スコア9567

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