回答編集履歴

3

「引数束縛」を追記

2018/04/22 15:12

投稿

think49
think49

スコア18164

test CHANGED
@@ -144,6 +144,58 @@
144
144
 
145
145
 
146
146
 
147
+ ### 引数束縛
148
+
149
+
150
+
151
+ 非クロージャ版で `Function.prototype.bind` を併用する事で、クロージャ版に近い動作にする事が出来ます。
152
+
153
+
154
+
155
+ ```JavaScript
156
+
157
+ sample1.bind(null, [fn1, fn2])(conditionfn, [5, '#']);
158
+
159
+ sample1.bind(null, [fn1, fn2]).bind(null, conditionfn)([5, '#']);
160
+
161
+ ```
162
+
163
+
164
+
165
+ しかしながら、`Function.prototype.bind` は第二引数の実を束縛する事が不可能なので、独自に引数束縛するコードを書いてみました。
166
+
167
+
168
+
169
+ - [bind-from-function.js: 任意のインデックスの引数束縛した関数を生成](https://gist.github.com/think49/59c9b5b7ca5b0b15cea5192046549fdf)
170
+
171
+
172
+
173
+ ```JavaScript
174
+
175
+ bindFromFunction(sample1, [,conditionfn])([fn1, fn2], null, [5, '#']);
176
+
177
+ ```
178
+
179
+
180
+
181
+ sample1 の関数設計を変える方が美しい設計かも…。
182
+
183
+
184
+
185
+ ```JavaScript
186
+
187
+ sample1({fn: [fn1, fn2], conditionfn: conditionfn, args: [5, '#'], thisArgs: thisArgs});
188
+
189
+ ```
190
+
191
+
192
+
193
+ これなら、`Function.prototype.bind` で束縛可能です。
194
+
195
+ (※引数束縛対象が単一なのに対し、`this` 束縛が関数ごとに独立しているのは、設計上美しくないかもしれません。お好みで変更して下さい。)
196
+
197
+
198
+
147
199
  ### 更新履歴
148
200
 
149
201
 
@@ -152,6 +204,8 @@
152
204
 
153
205
  - 2018/04/22 14:13 「コード (非クロージャ版)」を追記
154
206
 
207
+ - 2018/04/23 00:12 「引数束縛」を追記
208
+
155
209
 
156
210
 
157
211
  Re: murabito さん

2

「コード (非クロージャ版)」を追記

2018/04/22 15:12

投稿

think49
think49

スコア18164

test CHANGED
@@ -1,4 +1,4 @@
1
- ### 要件
1
+ ### コード (クロージャ版)
2
2
 
3
3
 
4
4
 
@@ -14,7 +14,27 @@
14
14
 
15
15
 
16
16
 
17
+ コード(文字数制限に引っかかったので、jsfiddleに移しました)。
18
+
19
+
20
+
21
+ - [クロージャ版 - JSFiddle](https://jsfiddle.net/njuacy78/)
22
+
23
+
24
+
25
+ 「this値固定」が汎用性に欠けますが、挙動を見る限りでは要件を満たしている気がします。
26
+
27
+
28
+
17
- ### コード (whileル版)
29
+ ### コード (非クロジャ版)
30
+
31
+
32
+
33
+ 全体的にクロージャを使用しない方がすっきりしますね。
34
+
35
+
36
+
37
+ - [非クロージャ版 - JSFiddle](https://jsfiddle.net/njuacy78/2/)
18
38
 
19
39
 
20
40
 
@@ -22,33 +42,71 @@
22
42
 
23
43
  'use strict';
24
44
 
25
- function enclosure (...fn) {
45
+ /**
26
46
 
27
- return function closure1 (number, ...args) {
47
+ * do-while
28
48
 
49
+ */
50
+
29
- number = Math.floor(number) || 0;
51
+ function sample1 (fn, continuefn, fnargs, thisArgs) {
52
+
53
+ let condition;
30
54
 
31
55
 
32
56
 
33
- return function closure2 () {
34
-
35
- while (number) {
36
-
37
- for (let i = 0, length = fn.length; i < length; ++i) {
57
+ thisArgs = Array.isArray(thisArgs) ? thisArgs : [];
38
-
39
- fn[i](...[number, ...args]);
40
-
41
- }
42
58
 
43
59
 
44
60
 
45
- --number;
61
+ do {
46
62
 
63
+ for (let i = 0, length = fn.length; i < length; ++i) {
64
+
47
- }
65
+ fn[i].apply(thisArgs[i], fnargs);
48
66
 
49
67
  }
50
68
 
69
+
70
+
71
+ condition = continuefn(...fnargs);
72
+
73
+ fnargs = condition[1];
74
+
75
+ } while (condition[0])
76
+
51
- };
77
+ }
78
+
79
+
80
+
81
+ /**
82
+
83
+ * 再帰版
84
+
85
+ */
86
+
87
+ function sample2 (fn, continuefn, fnargs, thisArgs) {
88
+
89
+ thisArgs = Array.isArray(thisArgs) ? thisArgs : [];
90
+
91
+
92
+
93
+ for (let i = 0, length = fn.length; i < length; ++i) {
94
+
95
+ fn[i].apply(thisArgs[i], fnargs);
96
+
97
+ }
98
+
99
+
100
+
101
+ const condition = continuefn(...fnargs);
102
+
103
+
104
+
105
+ if (condition[0]) {
106
+
107
+ sample2(fn, continuefn, condition[1], thisArgs);
108
+
109
+ }
52
110
 
53
111
  }
54
112
 
@@ -62,15 +120,7 @@
62
120
 
63
121
 
64
122
 
65
- function fn2 (number) {
66
-
67
- console.log('#'.repeat(number));
68
-
69
- }
70
-
71
-
72
-
73
- function fn3 (number, string) {
123
+ function fn2 (number, string) {
74
124
 
75
125
  console.log(string.repeat(number));
76
126
 
@@ -78,109 +128,29 @@
78
128
 
79
129
 
80
130
 
81
- enclosure(fn1, fn2)(5)();
131
+ function conditionfn (number, ...args) {
82
132
 
133
+ return [number > 0, [--number, ...args]];
134
+
135
+ }
136
+
137
+
138
+
83
- enclosure(fn1, fn3)(5, '@')();
139
+ sample1([fn1, fn2], conditionfn, [5, '#']);
140
+
141
+ sample2([fn1, fn2], conditionfn, [5, '#']);
84
142
 
85
143
  ```
86
144
 
87
145
 
88
146
 
89
- 「this値固定」が汎用性に欠けますが、挙動を見る限りでは要件を満たしている気がします。
147
+ ### 更新履歴
90
148
 
91
149
 
92
150
 
93
- ### コード (再帰関数)
151
+ - 2018/04/22 13:03 「コード (クロージャ版)」の再帰版を追記
94
152
 
95
-
96
-
97
- ```JavaScript
98
-
99
- function enclosure2 (...fn) {
100
-
101
- return function closure1 (number, ...args) {
102
-
103
- number = Math.floor(number) || 0;
104
-
105
-
106
-
107
- return function closure2 () {
108
-
109
- if (!number) {
110
-
111
- return;
112
-
113
- }
114
-
115
-
116
-
117
- for (let i = 0, length = fn.length; i < length; ++i) {
118
-
119
- fn[i](...[number, ...args]);
120
-
121
- }
122
-
123
-
124
-
125
- --number;
126
-
127
- closure2();
128
-
129
- }
130
-
131
- };
132
-
133
- }
134
-
135
-
136
-
137
- function fn1 () {
138
-
139
- console.log('-----');
140
-
141
- }
142
-
143
-
144
-
145
- function fn2 (number) {
146
-
147
- console.log('#'.repeat(number));
153
+ - 2018/04/22 14:13 「コード (非クロージャ版)」を追記
148
-
149
- }
150
-
151
-
152
-
153
- function fn3 (number, string) {
154
-
155
- console.log(string.repeat(number));
156
-
157
- }
158
-
159
-
160
-
161
- enclosure2(fn1, fn2)(5)();
162
-
163
- enclosure2(fn1, fn3)(5, '@')();
164
-
165
- ```
166
-
167
-
168
-
169
- ### this値を渡す
170
-
171
-
172
-
173
- `Array.prototype.forEach` のように、コールバック関数に this 値を渡せるようにすると汎用性が増します。
174
-
175
- `Function.prototype.apply` を使えば、this値を渡せますが、引数の渡し方をどうすべきなのでしょうね…。
176
-
177
-
178
-
179
- ```JavaScript
180
-
181
- enclosure(fn1, fn2)([arg1, arg2], [thisArg1, thisArg2])();
182
-
183
- ```
184
154
 
185
155
 
186
156
 

1

コード (再帰版)

2018/04/22 05:14

投稿

think49
think49

スコア18164

test CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
 
16
16
 
17
- ### コード
17
+ ### コード (whileループ版)
18
18
 
19
19
 
20
20
 
@@ -90,6 +90,82 @@
90
90
 
91
91
 
92
92
 
93
+ ### コード (再帰関数版)
94
+
95
+
96
+
97
+ ```JavaScript
98
+
99
+ function enclosure2 (...fn) {
100
+
101
+ return function closure1 (number, ...args) {
102
+
103
+ number = Math.floor(number) || 0;
104
+
105
+
106
+
107
+ return function closure2 () {
108
+
109
+ if (!number) {
110
+
111
+ return;
112
+
113
+ }
114
+
115
+
116
+
117
+ for (let i = 0, length = fn.length; i < length; ++i) {
118
+
119
+ fn[i](...[number, ...args]);
120
+
121
+ }
122
+
123
+
124
+
125
+ --number;
126
+
127
+ closure2();
128
+
129
+ }
130
+
131
+ };
132
+
133
+ }
134
+
135
+
136
+
137
+ function fn1 () {
138
+
139
+ console.log('-----');
140
+
141
+ }
142
+
143
+
144
+
145
+ function fn2 (number) {
146
+
147
+ console.log('#'.repeat(number));
148
+
149
+ }
150
+
151
+
152
+
153
+ function fn3 (number, string) {
154
+
155
+ console.log(string.repeat(number));
156
+
157
+ }
158
+
159
+
160
+
161
+ enclosure2(fn1, fn2)(5)();
162
+
163
+ enclosure2(fn1, fn3)(5, '@')();
164
+
165
+ ```
166
+
167
+
168
+
93
169
  ### this値を渡す
94
170
 
95
171