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

回答編集履歴

3

「引数束縛」を追記

2018/04/22 15:12

投稿

think49
think49

スコア18194

answer CHANGED
@@ -71,9 +71,36 @@
71
71
  sample2([fn1, fn2], conditionfn, [5, '#']);
72
72
  ```
73
73
 
74
+ ### 引数束縛
75
+
76
+ 非クロージャ版で `Function.prototype.bind` を併用する事で、クロージャ版に近い動作にする事が出来ます。
77
+
78
+ ```JavaScript
79
+ sample1.bind(null, [fn1, fn2])(conditionfn, [5, '#']);
80
+ sample1.bind(null, [fn1, fn2]).bind(null, conditionfn)([5, '#']);
81
+ ```
82
+
83
+ しかしながら、`Function.prototype.bind` は第二引数の実を束縛する事が不可能なので、独自に引数束縛するコードを書いてみました。
84
+
85
+ - [bind-from-function.js: 任意のインデックスの引数束縛した関数を生成](https://gist.github.com/think49/59c9b5b7ca5b0b15cea5192046549fdf)
86
+
87
+ ```JavaScript
88
+ bindFromFunction(sample1, [,conditionfn])([fn1, fn2], null, [5, '#']);
89
+ ```
90
+
91
+ sample1 の関数設計を変える方が美しい設計かも…。
92
+
93
+ ```JavaScript
94
+ sample1({fn: [fn1, fn2], conditionfn: conditionfn, args: [5, '#'], thisArgs: thisArgs});
95
+ ```
96
+
97
+ これなら、`Function.prototype.bind` で束縛可能です。
98
+ (※引数束縛対象が単一なのに対し、`this` 束縛が関数ごとに独立しているのは、設計上美しくないかもしれません。お好みで変更して下さい。)
99
+
74
100
  ### 更新履歴
75
101
 
76
102
  - 2018/04/22 13:03 「コード (クロージャ版)」の再帰版を追記
77
103
  - 2018/04/22 14:13 「コード (非クロージャ版)」を追記
104
+ - 2018/04/23 00:12 「引数束縛」を追記
78
105
 
79
106
  Re: murabito さん

2

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

2018/04/22 15:12

投稿

think49
think49

スコア18194

answer CHANGED
@@ -1,4 +1,4 @@
1
- ### 要件
1
+ ### コード (クロージャ版)
2
2
 
3
3
  ようするに、次の要素を「当該関数だけが参照可能な場所に閉じ込めたい」という事でしょうか。
4
4
 
@@ -6,89 +6,74 @@
6
6
  - コールバック関数
7
7
  - コールバック関数に渡される引数
8
8
 
9
- ### コード (whileループ版)
9
+ コード(文字数制限に引っかかったので、jsfiddleに移しました)
10
10
 
11
- ```JavaScript
12
- 'use strict';
13
- function enclosure (...fn) {
14
- return function closure1 (number, ...args) {
11
+ - [クロージャ版 - JSFiddle](https://jsfiddle.net/njuacy78/)
15
- number = Math.floor(number) || 0;
16
12
 
17
- return function closure2 () {
18
- while (number) {
19
- for (let i = 0, length = fn.length; i < length; ++i) {
13
+ 「this値固定」が汎用性に欠けますが、挙動を見る限りでは要件を満たしている気がします。
20
- fn[i](...[number, ...args]);
21
- }
22
14
 
23
- --number;
15
+ ### コード (非クロージャ版)
24
- }
25
- }
26
- };
27
- }
28
16
 
29
- function fn1 () {
30
- console.log('-----');
17
+ 全体的にクロージャを使用しない方がすっきりしますね。
31
- }
32
18
 
33
- function fn2 (number) {
34
- console.log('#'.repeat(number));
19
+ - [非クロージャ版 - JSFiddle](https://jsfiddle.net/njuacy78/2/)
35
- }
36
20
 
21
+ ```JavaScript
22
+ 'use strict';
23
+ /**
24
+ * do-while版
25
+ */
37
- function fn3 (number, string) {
26
+ function sample1 (fn, continuefn, fnargs, thisArgs) {
38
- console.log(string.repeat(number));
27
+ let condition;
39
- }
40
28
 
41
- enclosure(fn1, fn2)(5)();
42
- enclosure(fn1, fn3)(5, '@')();
29
+ thisArgs = Array.isArray(thisArgs) ? thisArgs : [];
43
- ```
44
30
 
31
+ do {
45
- 「this値固定」が汎用性に欠けますが、挙動を見る限りでは要件を満たしている気がします。
32
+ for (let i = 0, length = fn.length; i < length; ++i) {
33
+ fn[i].apply(thisArgs[i], fnargs);
34
+ }
46
35
 
36
+ condition = continuefn(...fnargs);
37
+ fnargs = condition[1];
47
- ### コード (再帰関数版)
38
+ } while (condition[0])
39
+ }
48
40
 
49
- ```JavaScript
41
+ /**
42
+ * 再帰版
50
- function enclosure2 (...fn) {
43
+ */
51
- return function closure1 (number, ...args) {
44
+ function sample2 (fn, continuefn, fnargs, thisArgs) {
52
- number = Math.floor(number) || 0;
45
+ thisArgs = Array.isArray(thisArgs) ? thisArgs : [];
53
46
 
54
- return function closure2 () {
47
+ for (let i = 0, length = fn.length; i < length; ++i) {
55
- if (!number) {
48
+ fn[i].apply(thisArgs[i], fnargs);
56
- return;
57
- }
49
+ }
58
50
 
59
- for (let i = 0, length = fn.length; i < length; ++i) {
60
- fn[i](...[number, ...args]);
51
+ const condition = continuefn(...fnargs);
61
- }
62
52
 
63
- --number;
64
- closure2();
53
+ if (condition[0]) {
54
+ sample2(fn, continuefn, condition[1], thisArgs);
65
- }
55
+ }
66
- };
67
56
  }
68
57
 
69
58
  function fn1 () {
70
59
  console.log('-----');
71
60
  }
72
61
 
73
- function fn2 (number) {
62
+ function fn2 (number, string) {
74
- console.log('#'.repeat(number));
63
+ console.log(string.repeat(number));
75
64
  }
76
65
 
77
- function fn3 (number, string) {
66
+ function conditionfn (number, ...args) {
78
- console.log(string.repeat(number));
67
+ return [number > 0, [--number, ...args]];
79
68
  }
80
69
 
81
- enclosure2(fn1, fn2)(5)();
82
- enclosure2(fn1, fn3)(5, '@')();
70
+ sample1([fn1, fn2], conditionfn, [5, '#']);
71
+ sample2([fn1, fn2], conditionfn, [5, '#']);
83
72
  ```
84
73
 
85
- ### this値を渡す
74
+ ### 更新履歴
86
75
 
87
- `Array.prototype.forEach` のように、コールバック関数に this 値渡せるようにすると汎用性が増します。
76
+ - 2018/04/22 13:03 「コー (クロージャ版)」の再帰版追記
88
- `Function.prototype.apply`使えば、this値を渡せますが、引数の渡し方をどうすべきなのでしょうね…。
77
+ - 2018/04/22 14:13 「コード (非クロージャ版)」追記
89
78
 
90
- ```JavaScript
91
- enclosure(fn1, fn2)([arg1, arg2], [thisArg1, thisArg2])();
92
- ```
93
-
94
79
  Re: murabito さん

1

コード (再帰版)

2018/04/22 05:14

投稿

think49
think49

スコア18194

answer CHANGED
@@ -6,7 +6,7 @@
6
6
  - コールバック関数
7
7
  - コールバック関数に渡される引数
8
8
 
9
- ### コード
9
+ ### コード (whileループ版)
10
10
 
11
11
  ```JavaScript
12
12
  'use strict';
@@ -44,6 +44,44 @@
44
44
 
45
45
  「this値固定」が汎用性に欠けますが、挙動を見る限りでは要件を満たしている気がします。
46
46
 
47
+ ### コード (再帰関数版)
48
+
49
+ ```JavaScript
50
+ function enclosure2 (...fn) {
51
+ return function closure1 (number, ...args) {
52
+ number = Math.floor(number) || 0;
53
+
54
+ return function closure2 () {
55
+ if (!number) {
56
+ return;
57
+ }
58
+
59
+ for (let i = 0, length = fn.length; i < length; ++i) {
60
+ fn[i](...[number, ...args]);
61
+ }
62
+
63
+ --number;
64
+ closure2();
65
+ }
66
+ };
67
+ }
68
+
69
+ function fn1 () {
70
+ console.log('-----');
71
+ }
72
+
73
+ function fn2 (number) {
74
+ console.log('#'.repeat(number));
75
+ }
76
+
77
+ function fn3 (number, string) {
78
+ console.log(string.repeat(number));
79
+ }
80
+
81
+ enclosure2(fn1, fn2)(5)();
82
+ enclosure2(fn1, fn3)(5, '@')();
83
+ ```
84
+
47
85
  ### this値を渡す
48
86
 
49
87
  `Array.prototype.forEach` のように、コールバック関数に this 値を渡せるようにすると汎用性が増します。