回答編集履歴

4

シャローコピーだとstateが壊れちゃって駄目だったので再修正

2017/08/25 01:17

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  // この方法は楽だけど、正規表現やDateみたいなインスタンスが来ると困る
12
12
 
13
- JSON.stringify(JSON.parse(state));
13
+ JSON.parse(JSON.stringify(state));
14
14
 
15
15
 
16
16
 
@@ -46,7 +46,7 @@
46
46
 
47
47
  再帰呼び出しでコツコツ作っていくしかない。
48
48
 
49
- 結論、`JSON.stringify(JSON.parse(state))`で解決出来なければライブラリ使うべき。
49
+ 結論、`JSON.parse(JSON.stringify(state))`で解決出来なければライブラリ使うべき。
50
50
 
51
51
 
52
52
 
@@ -76,7 +76,15 @@
76
76
 
77
77
  `to_state`の部分は関数として切り出せたから楽にテスト出来るね。
78
78
 
79
- しかしpushが副作用のある破壊的メソッドだから、毎回シャローコピーする重い処理になったけ、これ関数型プログラミング的にはあるべき姿と思う
79
+ しかしpushが破壊的メソッドだからどう扱うかJSの課題
80
+
81
+ ディープコピーをしないとすぐにstateが壊れる。
82
+
83
+
84
+
85
+ 草案だとmergeの最初でシャローコピーしてたけどそれじゃ駄目で、
86
+
87
+ ディープコピーが必要になったので`clone`というメソッドを作って入り口で作って対応した。
80
88
 
81
89
 
82
90
 
@@ -118,9 +126,9 @@
118
126
 
119
127
 
120
128
 
121
- const to_state = (state, it) => {
129
+ const clone = (it) => JSON.parse(JSON.stringify(it))
122
130
 
123
- let data = Object.assign({}, state);
131
+ const merge = (data, it) => {
124
132
 
125
133
  if (data[it.id] == null) data[it.id] = [];
126
134
 
@@ -132,7 +140,7 @@
132
140
 
133
141
 
134
142
 
135
- console.log(payload.reduce(to_state, state));
143
+ console.log(payload.reduce(merge, clone(state)));
136
144
 
137
145
  // Object {100: Array(2), 001: Array(4), 010: Array(2)}
138
146
 
@@ -140,6 +148,6 @@
140
148
 
141
149
  console.log(state);
142
150
 
143
- // Object {001: Array(4), 010: Array(2)}
151
+ // Object {001: Array(2), 010: Array(2)}
144
152
 
145
153
  ```

3

あれ、1と2は違うじゃん。というわけで1も回答

2017/08/25 01:17

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -1,3 +1,55 @@
1
+ > (1)Deep Copyするには?(ライブラリで解決する方法は既に把握済みですが、ライブラリを使わない場合はどう書くのか?
2
+
3
+
4
+
5
+ さりげに難問
6
+
7
+
8
+
9
+ ```JavaScript
10
+
11
+ // この方法は楽だけど、正規表現やDateみたいなインスタンスが来ると困る
12
+
13
+ JSON.stringify(JSON.parse(state));
14
+
15
+
16
+
17
+ // これは駄目
18
+
19
+ var hoge = {a: [1, 2, 3], b: 123};
20
+
21
+ var piko = Object.entries(hoge).reduce((a, it) => {
22
+
23
+ a[it[0]] = it[1];
24
+
25
+ return a;
26
+
27
+ }. {});
28
+
29
+ piko.a.push(5); // こんな風に破壊的な修正を加えると…
30
+
31
+
32
+
33
+ console.log(hoge);
34
+
35
+ // {a: [1, 2, 3, 5], b: 123} ←配列の参照が残ってるのでこっちも変更されてしまう
36
+
37
+
38
+
39
+ console.log(piko);
40
+
41
+ // {a: [1, 2, 3, 5], b: 123}
42
+
43
+ ```
44
+
45
+
46
+
47
+ 再帰呼び出しでコツコツ作っていくしかない。
48
+
49
+ 結論、`JSON.stringify(JSON.parse(state))`で解決出来なければライブラリ使うべき。
50
+
51
+
52
+
1
53
  > (2)forEachは値をreturn出来ないが、forEachを使わず副作用の無いように書くにはどうしたら良いのか?
2
54
 
3
55
 
@@ -13,10 +65,6 @@
13
65
  `forEach`(もしくはeach)は順番に実行するという意味を持つ。
14
66
 
15
67
  Ajaxを飛ばすとか、console.logで出力するとか、副作用のあるものをバシバシ実行していくためのもの。
16
-
17
-
18
-
19
- > (1)Deep Copyするには?(ライブラリで解決する方法は既に把握済みですが、ライブラリを使わない場合はどう書くのか?
20
68
 
21
69
 
22
70
 

2

constしたdataにpushはイケてないのでletに修正

2017/08/24 15:21

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
  `to_state`の部分は関数として切り出せたから楽にテスト出来るね。
30
30
 
31
- しかし、pushが副作用のあるプロトタイプメソッドでイケてないので、毎回シャローコピーする重い処理になったけど、これが関数型プログラミング的にはあるべき姿だと思う。
31
+ しかし、pushが副作用のある破壊的メソッドだから、毎回シャローコピーする重い処理になったけど、これが関数型プログラミング的にはあるべき姿だと思う。
32
32
 
33
33
 
34
34
 
@@ -72,7 +72,7 @@
72
72
 
73
73
  const to_state = (state, it) => {
74
74
 
75
- const data = Object.assign({}, state);
75
+ let data = Object.assign({}, state);
76
76
 
77
77
  if (data[it.id] == null) data[it.id] = [];
78
78
 

1

副作用があったので修正

2017/08/24 14:21

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -26,11 +26,9 @@
26
26
 
27
27
 
28
28
 
29
- 速度はthink49さんが出したようなfor文を使うやり方にかないっこないんだけど、
30
-
31
29
  `to_state`の部分は関数として切り出せたから楽にテスト出来るね。
32
30
 
33
- ついでにリファクタリングて3行にしてたよ!(読みやなったとは言っていない)
31
+ 、pushが副作用のあるプロトタイプメソッドでイケので、毎回シャローコピーる重い処理になったけど、これが関数型プログラミング的にはあるべき姿だ思う。
34
32
 
35
33
 
36
34
 
@@ -50,20 +48,50 @@
50
48
 
51
49
 
52
50
 
53
- const to_state = (state, it) => {
51
+ const state = {
54
52
 
55
- if (state[it.id] == null) state[it.id] = [];
53
+ '001': [
56
54
 
57
- state[it.id].push(it);
55
+ {id: '001', score: 142},
58
56
 
57
+ {id: '001', score: 112}
58
+
59
+ ],
60
+
59
- return state;
61
+ '010': [
62
+
63
+ {id: '010', score: 142},
64
+
65
+ {id: '010', score: 112}
66
+
67
+ ]
60
68
 
61
69
  }
62
70
 
63
71
 
64
72
 
65
- console.log(payload.reduce(to_state, {}));
73
+ const to_state = (state, it) => {
66
74
 
75
+ const data = Object.assign({}, state);
76
+
77
+ if (data[it.id] == null) data[it.id] = [];
78
+
79
+ data[it.id].push(it);
80
+
81
+ return data;
82
+
83
+ }
84
+
85
+
86
+
87
+ console.log(payload.reduce(to_state, state));
88
+
89
+ // Object {100: Array(2), 001: Array(4), 010: Array(2)}
90
+
91
+
92
+
93
+ console.log(state);
94
+
67
- // Object {100: Array(2), 001: Array(2)}
95
+ // Object {001: Array(4), 010: Array(2)}
68
96
 
69
97
  ```