回答編集履歴

5

Function#bind のサンプルをjsfiddleにUP

2016/01/19 14:53

投稿

think49
think49

スコア18162

test CHANGED
@@ -176,7 +176,11 @@
176
176
 
177
177
 
178
178
 
179
- もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデアです)。
179
+ もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデア)。
180
+
181
+ jsfiddleにサンプルをUPしています。
182
+
183
+ - [Function#bind で this 値を束縛する - JSFiddle](https://jsfiddle.net/066ko0qg/)
180
184
 
181
185
 
182
186
 

4

pointA, pointC がインクリメントされていなかった不具合修正

2016/01/19 14:53

投稿

think49
think49

スコア18162

test CHANGED
@@ -78,9 +78,11 @@
78
78
 
79
79
  updateResizeData: function updateResizeData () {
80
80
 
81
- this.data.pointA = this.data.pointA++;
81
+ var data = this.data;
82
+
82
-
83
+ ++data.pointA; // (修正) インクリメントされていなかった不具合を修正
84
+
83
- this.data.pointC = this.data.pointC++;
85
+ ++data.pointC; // (修正) インクリメントされていなかった不具合を修正
84
86
 
85
87
  },
86
88
 

3

Lhankor_Mhy さんのアイデアをお借りして `initialEvent\(\)` 時に予め `bind` しておくコードを追加

2016/01/19 14:37

投稿

think49
think49

スコア18162

test CHANGED
@@ -28,168 +28,216 @@
28
28
 
29
29
  'use strict';
30
30
 
31
- function SampleClassA () {
31
+ function SampleClassA () { ; }
32
+
33
+
34
+
32
-
35
+ SampleClassA.prototype = { // (修正) SampleClassAに修正
36
+
37
+ setDefaultData: function setDefaultData () {
38
+
33
- this.data;
39
+ this.data = {
40
+
34
-
41
+ pointA: 10,
42
+
43
+ pointB: 10,
44
+
45
+ pointC: 10,
46
+
47
+ pointD: 10
48
+
49
+ };
50
+
51
+ },
52
+
53
+ doDisplay: function doDisplay (/* [window] */) {
54
+
55
+ // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
56
+
57
+
58
+
59
+ if (arguments.length > 0) {
60
+
61
+ var window = arguments[0];
62
+
63
+ console.log(window.innerWidth, window.innerHeight);
64
+
65
+ }
66
+
67
+ console.log(this.data);
68
+
69
+ },
70
+
71
+ initialEvent: function initialEvent () {
72
+
73
+ this.setDefaultData(); // (修正) 関数呼び出しする
74
+
75
+ this.doDisplay(); // (修正) 関数呼び出しする
76
+
77
+ },
78
+
79
+ updateResizeData: function updateResizeData () {
80
+
81
+ this.data.pointA = this.data.pointA++;
82
+
83
+ this.data.pointC = this.data.pointC++;
84
+
85
+ },
86
+
87
+ resizeEvent: function resizeEvent (event) {
88
+
35
- this.object;
89
+ console.log(event);
90
+
91
+ this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
92
+
93
+ this.doDisplay(event.target); // (修正) 関数呼び出しする
94
+
95
+ }
96
+
97
+ };
98
+
99
+
100
+
101
+ SampleClassA.prototype.initialEvent = function initialEvent () {
102
+
103
+ this.resizeEvent = this.resizeEvent.bind(this);
104
+
105
+ this.setDefaultData(); // (修正) 関数呼び出しする
106
+
107
+ this.doDisplay(); // (修正) 関数呼び出しする
36
108
 
37
109
  }
38
110
 
111
+
112
+
113
+ // (修正) 呼び出しコードを後ろに持ってくる
114
+
115
+ var sampleA1 = new SampleClassA();
116
+
117
+ //初期イベント
118
+
119
+ sampleA1.initialEvent();
120
+
121
+ //windowサイズ変更時のイベント等
122
+
123
+ jQuery(window).on('resize', sampleA1.resizeEvent);
124
+
125
+ ```
126
+
127
+
128
+
129
+ ## 解決法
130
+
131
+
132
+
133
+ # (方法1) `addEventListener` の `handleEvent` を使う
134
+
135
+
136
+
137
+ ```JavaScript
138
+
39
- SampleClassA.prototype = { // (修正) SampleClassAに修正
139
+ SampleClassA.prototype.handleEvent = function handleEvent (event) {
40
-
140
+
41
- setDefaultData: function setDefaultData () {
141
+ this.updateResizeData();
42
-
142
+
43
- this.data = {
143
+ this.doDisplay();
44
-
45
- pointA: 10,
144
+
46
-
47
- pointB: 10,
48
-
49
- pointC: 10,
50
-
51
- pointD: 10,
52
-
53
- };
54
-
55
- return true;
145
+ return true;
56
-
57
- },
58
-
59
- doDisplay: function doDisplay (/* [window] */) {
60
-
61
- // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
62
-
63
-
64
-
65
- if (arguments.length > 0) {
66
-
67
- var window = arguments[0];
68
-
69
- console.log(window.innerWidth, window.innerHeight);
70
-
71
- }
72
-
73
- console.log(this.data);
74
-
75
- return true;
76
-
77
- },
78
-
79
- initialEvent: function initialEvent () {
80
-
81
- this.setDefaultData(); // (修正) 関数呼び出しする
82
-
83
- this.doDisplay(); // (修正) 関数呼び出しする
84
-
85
- return true;
86
-
87
- },
88
-
89
- updateResizeData: function updateResizeData () {
90
-
91
- this.data.pointA = this.data.pointA++;
92
-
93
- this.data.pointC = this.data.pointC++;
94
-
95
- return true;
96
-
97
- },
98
-
99
- resizeEvent: function resizeEvent (event) {
100
-
101
- this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
102
-
103
- this.doDisplay(event.target); // (修正) 関数呼び出しする
104
-
105
- return true;
106
-
107
- },
108
146
 
109
147
  };
110
148
 
111
149
 
112
150
 
113
- // (修正) 呼び出しコードを後ろに持ってくる
114
-
115
- var sampleA1 = new SampleClassA();
151
+ var sampleA1 = new SampleClassA();
116
-
117
- //初期イベント
152
+
118
-
119
- sampleA1.initialEvent();
153
+ sampleA1.initialEvent();
120
-
121
- //windowサイズ変更時のイベント等
154
+
122
-
123
- jQuery(window).on('resize', sampleA1.resizeEvent);
155
+ addEventListener('resize', sampleA1, false);
124
-
156
+
125
- ```
157
+ ```
126
-
127
-
128
-
129
- ## 解決法
158
+
130
-
131
-
132
-
159
+
160
+
133
- # (方法1) `addEventListener` の `handleEvent` を使う
161
+ # (方法2) `Function.prototype.bind` を使う
162
+
163
+
164
+
134
-
165
+ 一つは `onresize` のイベント定義時に `bind` する方法。
135
-
136
-
166
+
167
+
168
+
137
- ```JavaScript
169
+ ```JavaScript
170
+
138
-
171
+ jQuery(window).on('resize', sampleA1.resizeEvent.bind(sampleA1));
172
+
173
+ ```
174
+
175
+
176
+
177
+ もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデアです)。
178
+
179
+
180
+
181
+ ```JavaScript
182
+
139
- SampleClassA.prototype.handleEvent = function handleEvent (event) {
183
+ SampleClassA.prototype.initialEvent = function initialEvent () {
184
+
140
-
185
+ this.resizeEvent = this.resizeEvent.bind(this); // 予め bind しておく
186
+
141
- this.updateResizeData();
187
+ this.setDefaultData();
142
188
 
143
189
  this.doDisplay();
144
190
 
191
+ }
192
+
193
+
194
+
195
+ var sampleA1 = new SampleClassA();
196
+
197
+ sampleA1.initialEvent();
198
+
199
+ jQuery(window).on('resize', sampleA1.resizeEvent); // bind 済みの resizeEvent を指定する
200
+
201
+
202
+
203
+ /**
204
+
205
+ * ただし、sampleA1.resizeEvent は bind 済みの為、後から Function.prototype.call で this 値を変更できない(意図的に汎用的ではない)
206
+
207
+ * this 値を変更するためには SampleClassA.prototype.resizeEvent を経由する必要がある
208
+
209
+ */
210
+
211
+ console.log(sampleA1.resizeEvent !== SampleClassA.prototype.resizeEvent); // true
212
+
213
+ sampleA1.resizeEvent.call(null, {target:{innerWidth: 777, innerHeight: 777}}); // Function.prototype.bind で束縛された this 値は書き換え不可能な為、TypeError にならない
214
+
215
+ SampleClassA.prototype.resizeEvent.call({updateResizeData: Function(), doDisplay: console.log.bind(console)}, {target:{innerWidth: 777, innerHeight: 777}}); // bind されていない為、this 値を変更できる
216
+
217
+ ```
218
+
219
+
220
+
221
+ # (方法3) `event.data` (jQuery API) を使う
222
+
223
+
224
+
225
+ - [event.data | jQuery API Documentation](https://api.jquery.com/event.data/)
226
+
227
+
228
+
229
+ ```JavaScript
230
+
231
+ SampleClassA.prototype.resizeEvent = function resizeEvent (event) {
232
+
233
+ var thisArg = event.data.thisArg;
234
+
235
+ thisArg.updateResizeData();
236
+
237
+ thisArg.doDisplay();
238
+
145
239
  return true;
146
240
 
147
- };
148
-
149
-
150
-
151
- var sampleA1 = new SampleClassA();
152
-
153
- sampleA1.initialEvent();
154
-
155
- addEventListener('resize', sampleA1, false);
156
-
157
- ```
158
-
159
-
160
-
161
- # (方法2) `Function.prototype.bind` を使う
162
-
163
-
164
-
165
- ```JavaScript
166
-
167
- jQuery(window).on('resize', sampleA1.resizeEvent.bind(sampleA1));
168
-
169
- ```
170
-
171
-
172
-
173
- # (方法3) `event.data` (jQuery API) を使う
174
-
175
-
176
-
177
- - [event.data | jQuery API Documentation](https://api.jquery.com/event.data/)
178
-
179
-
180
-
181
- ```JavaScript
182
-
183
- SampleClassA.prototype.resizeEvent = function resizeEvent (event) {
184
-
185
- var thisArg = event.data.thisArg;
186
-
187
- thisArg.updateResizeData();
188
-
189
- thisArg.doDisplay();
190
-
191
- return true;
192
-
193
241
  }
194
242
 
195
243
 
@@ -212,4 +260,14 @@
212
260
 
213
261
 
214
262
 
263
+ ## 更新履歴
264
+
265
+
266
+
267
+ **(2016/1/19 23:28追記)**
268
+
269
+ Lhankor_Mhy さんのアイデアをお借りして `initialEvent()` 時に予め `bind` しておくコードを追加しました。
270
+
271
+
272
+
215
273
  Re: ゲストユーザーさん

2

setDefaultData の関数名追加

2016/01/19 14:28

投稿

think49
think49

スコア18162

test CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  SampleClassA.prototype = { // (修正) SampleClassAに修正
40
40
 
41
- setDefaultData: function() {
41
+ setDefaultData: function setDefaultData () {
42
42
 
43
43
  this.data = {
44
44
 

1

SampleClassA\.prototype\.doDisplay のコード調整\(resize時の動作がわかりやすいように\)

2016/01/19 14:03

投稿

think49
think49

スコア18162

test CHANGED
@@ -26,71 +26,85 @@
26
26
 
27
27
  ```JavaScript
28
28
 
29
+ 'use strict';
30
+
29
- function SampleClassA() {
31
+ function SampleClassA () {
30
-
32
+
31
- this.data;
33
+ this.data;
32
-
34
+
33
- this.object;
35
+ this.object;
34
36
 
35
37
  }
36
38
 
37
39
  SampleClassA.prototype = { // (修正) SampleClassAに修正
38
40
 
39
- setDefaultData: function() {
40
-
41
- this.data = {
42
-
43
- pointA: 10,
44
-
45
- pointB: 10,
46
-
47
- pointC: 10,
48
-
49
- pointD: 10,
50
-
51
- };
52
-
53
- return true;
54
-
55
- },
56
-
57
- doDisplay: function() {
58
-
59
- // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
60
-
61
- return true;
62
-
63
- },
64
-
65
- initialEvent: function() {
66
-
67
- this.setDefaultData(); // (修正) 関数呼び出しする
68
-
69
- this.doDisplay(); // (修正) 関数呼び出しする
70
-
71
- return true;
72
-
73
- },
74
-
75
- updateResizeData: function() {
76
-
77
- this.data.pointA = this.data.pointA++;
78
-
79
- this.data.pointC = this.data.pointC++;
80
-
81
- return true;
82
-
83
- },
84
-
85
- resizeEvent: function() {
86
-
87
- this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
88
-
89
- this.doDisplay(); // (修正) 関数呼び出しする
90
-
91
- return true;
92
-
93
- },
41
+ setDefaultData: function() {
42
+
43
+ this.data = {
44
+
45
+ pointA: 10,
46
+
47
+ pointB: 10,
48
+
49
+ pointC: 10,
50
+
51
+ pointD: 10,
52
+
53
+ };
54
+
55
+ return true;
56
+
57
+ },
58
+
59
+ doDisplay: function doDisplay (/* [window] */) {
60
+
61
+ // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
62
+
63
+
64
+
65
+ if (arguments.length > 0) {
66
+
67
+ var window = arguments[0];
68
+
69
+ console.log(window.innerWidth, window.innerHeight);
70
+
71
+ }
72
+
73
+ console.log(this.data);
74
+
75
+ return true;
76
+
77
+ },
78
+
79
+ initialEvent: function initialEvent () {
80
+
81
+ this.setDefaultData(); // (修正) 関数呼び出しする
82
+
83
+ this.doDisplay(); // (修正) 関数呼び出しする
84
+
85
+ return true;
86
+
87
+ },
88
+
89
+ updateResizeData: function updateResizeData () {
90
+
91
+ this.data.pointA = this.data.pointA++;
92
+
93
+ this.data.pointC = this.data.pointC++;
94
+
95
+ return true;
96
+
97
+ },
98
+
99
+ resizeEvent: function resizeEvent (event) {
100
+
101
+ this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
102
+
103
+ this.doDisplay(event.target); // (修正) 関数呼び出しする
104
+
105
+ return true;
106
+
107
+ },
94
108
 
95
109
  };
96
110
 
@@ -106,7 +120,7 @@
106
120
 
107
121
  //windowサイズ変更時のイベント等
108
122
 
109
- $(window).on('resize', sampleA1.resizeEvent);
123
+ jQuery(window).on('resize', sampleA1.resizeEvent);
110
124
 
111
125
  ```
112
126