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

回答編集履歴

5

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

2016/01/19 14:53

投稿

think49
think49

スコア18194

answer CHANGED
@@ -87,7 +87,9 @@
87
87
  jQuery(window).on('resize', sampleA1.resizeEvent.bind(sampleA1));
88
88
  ```
89
89
 
90
- もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデアです)。
90
+ もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデア)。
91
+ jsfiddleにサンプルをUPしています。
92
+ - [Function#bind で this 値を束縛する - JSFiddle](https://jsfiddle.net/066ko0qg/)
91
93
 
92
94
  ```JavaScript
93
95
  SampleClassA.prototype.initialEvent = function initialEvent () {

4

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

2016/01/19 14:53

投稿

think49
think49

スコア18194

answer CHANGED
@@ -38,8 +38,9 @@
38
38
  this.doDisplay(); // (修正) 関数呼び出しする
39
39
  },
40
40
  updateResizeData: function updateResizeData () {
41
- this.data.pointA = this.data.pointA++;
41
+ var data = this.data;
42
+ ++data.pointA; // (修正) インクリメントされていなかった不具合を修正
42
- this.data.pointC = this.data.pointC++;
43
+ ++data.pointC; // (修正) インクリメントされていなかった不具合を修正
43
44
  },
44
45
  resizeEvent: function resizeEvent (event) {
45
46
  console.log(event);

3

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

2016/01/19 14:37

投稿

think49
think49

スコア18194

answer CHANGED
@@ -13,19 +13,16 @@
13
13
 
14
14
  ```JavaScript
15
15
  'use strict';
16
- function SampleClassA () {
16
+ function SampleClassA () { ; }
17
- this.data;
17
+
18
- this.object;
19
- }
20
18
  SampleClassA.prototype = { // (修正) SampleClassAに修正
21
19
  setDefaultData: function setDefaultData () {
22
20
  this.data = {
23
21
  pointA: 10,
24
22
  pointB: 10,
25
23
  pointC: 10,
26
- pointD: 10,
24
+ pointD: 10
27
25
  };
28
- return true;
29
26
  },
30
27
  doDisplay: function doDisplay (/* [window] */) {
31
28
  // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
@@ -35,25 +32,28 @@
35
32
  console.log(window.innerWidth, window.innerHeight);
36
33
  }
37
34
  console.log(this.data);
38
- return true;
39
35
  },
40
36
  initialEvent: function initialEvent () {
41
37
  this.setDefaultData(); // (修正) 関数呼び出しする
42
38
  this.doDisplay(); // (修正) 関数呼び出しする
43
- return true;
44
39
  },
45
40
  updateResizeData: function updateResizeData () {
46
41
  this.data.pointA = this.data.pointA++;
47
42
  this.data.pointC = this.data.pointC++;
48
- return true;
49
43
  },
50
44
  resizeEvent: function resizeEvent (event) {
45
+ console.log(event);
51
46
  this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
52
47
  this.doDisplay(event.target); // (修正) 関数呼び出しする
53
- return true;
54
- },
48
+ }
55
49
  };
56
50
 
51
+ SampleClassA.prototype.initialEvent = function initialEvent () {
52
+ this.resizeEvent = this.resizeEvent.bind(this);
53
+ this.setDefaultData(); // (修正) 関数呼び出しする
54
+ this.doDisplay(); // (修正) 関数呼び出しする
55
+ }
56
+
57
57
  // (修正) 呼び出しコードを後ろに持ってくる
58
58
  var sampleA1 = new SampleClassA();
59
59
  //初期イベント
@@ -80,10 +80,34 @@
80
80
 
81
81
  # (方法2) `Function.prototype.bind` を使う
82
82
 
83
+ 一つは `onresize` のイベント定義時に `bind` する方法。
84
+
83
85
  ```JavaScript
84
86
  jQuery(window).on('resize', sampleA1.resizeEvent.bind(sampleA1));
85
87
  ```
86
88
 
89
+ もう一つは `initialEvent()` 時に予め `bind` しておく方法(Lhankor_Mhy さんのアイデアです)。
90
+
91
+ ```JavaScript
92
+ SampleClassA.prototype.initialEvent = function initialEvent () {
93
+ this.resizeEvent = this.resizeEvent.bind(this); // 予め bind しておく
94
+ this.setDefaultData();
95
+ this.doDisplay();
96
+ }
97
+
98
+ var sampleA1 = new SampleClassA();
99
+ sampleA1.initialEvent();
100
+ jQuery(window).on('resize', sampleA1.resizeEvent); // bind 済みの resizeEvent を指定する
101
+
102
+ /**
103
+ * ただし、sampleA1.resizeEvent は bind 済みの為、後から Function.prototype.call で this 値を変更できない(意図的に汎用的ではない)
104
+ * this 値を変更するためには SampleClassA.prototype.resizeEvent を経由する必要がある
105
+ */
106
+ console.log(sampleA1.resizeEvent !== SampleClassA.prototype.resizeEvent); // true
107
+ sampleA1.resizeEvent.call(null, {target:{innerWidth: 777, innerHeight: 777}}); // Function.prototype.bind で束縛された this 値は書き換え不可能な為、TypeError にならない
108
+ SampleClassA.prototype.resizeEvent.call({updateResizeData: Function(), doDisplay: console.log.bind(console)}, {target:{innerWidth: 777, innerHeight: 777}}); // bind されていない為、this 値を変更できる
109
+ ```
110
+
87
111
  # (方法3) `event.data` (jQuery API) を使う
88
112
 
89
113
  - [event.data | jQuery API Documentation](https://api.jquery.com/event.data/)
@@ -105,4 +129,9 @@
105
129
 
106
130
  jQuery に拘りがないのなら `addEventListener` の `handleEvent` を使う方法が最もスマートだと思います。
107
131
 
132
+ ## 更新履歴
133
+
134
+ **(2016/1/19 23:28追記)**
135
+ Lhankor_Mhy さんのアイデアをお借りして `initialEvent()` 時に予め `bind` しておくコードを追加しました。
136
+
108
137
  Re: ゲストユーザーさん

2

setDefaultData の関数名追加

2016/01/19 14:28

投稿

think49
think49

スコア18194

answer CHANGED
@@ -18,7 +18,7 @@
18
18
  this.object;
19
19
  }
20
20
  SampleClassA.prototype = { // (修正) SampleClassAに修正
21
- setDefaultData: function() {
21
+ setDefaultData: function setDefaultData () {
22
22
  this.data = {
23
23
  pointA: 10,
24
24
  pointB: 10,

1

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

2016/01/19 14:03

投稿

think49
think49

スコア18194

answer CHANGED
@@ -12,39 +12,46 @@
12
12
  (地味に手間なのでサンプルでも動く事を確認してから掲載するようにしていただけると助かります)
13
13
 
14
14
  ```JavaScript
15
+ 'use strict';
15
- function SampleClassA() {
16
+ function SampleClassA () {
16
- this.data;
17
+ this.data;
17
- this.object;
18
+ this.object;
18
19
  }
19
20
  SampleClassA.prototype = { // (修正) SampleClassAに修正
20
- setDefaultData: function() {
21
+ setDefaultData: function() {
21
- this.data = {
22
+ this.data = {
22
- pointA: 10,
23
+ pointA: 10,
23
- pointB: 10,
24
+ pointB: 10,
24
- pointC: 10,
25
+ pointC: 10,
25
- pointD: 10,
26
+ pointD: 10,
26
- };
27
+ };
27
- return true;
28
+ return true;
28
- },
29
+ },
29
- doDisplay: function() {
30
+ doDisplay: function doDisplay (/* [window] */) {
30
- // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
31
+ // this.object = new SampleLibrary.display(this.data); // (修正) ReferenceError の為、コメントアウト
32
+
33
+ if (arguments.length > 0) {
34
+ var window = arguments[0];
35
+ console.log(window.innerWidth, window.innerHeight);
36
+ }
37
+ console.log(this.data);
31
- return true;
38
+ return true;
32
- },
39
+ },
33
- initialEvent: function() {
40
+ initialEvent: function initialEvent () {
34
- this.setDefaultData(); // (修正) 関数呼び出しする
41
+ this.setDefaultData(); // (修正) 関数呼び出しする
35
- this.doDisplay(); // (修正) 関数呼び出しする
42
+ this.doDisplay(); // (修正) 関数呼び出しする
36
- return true;
43
+ return true;
37
- },
44
+ },
38
- updateResizeData: function() {
45
+ updateResizeData: function updateResizeData () {
39
- this.data.pointA = this.data.pointA++;
46
+ this.data.pointA = this.data.pointA++;
40
- this.data.pointC = this.data.pointC++;
47
+ this.data.pointC = this.data.pointC++;
41
- return true;
48
+ return true;
42
- },
49
+ },
43
- resizeEvent: function() {
50
+ resizeEvent: function resizeEvent (event) {
44
- this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
51
+ this.updateResizeData(); // TypeError: this.updateResizeData is not a function (修正) 関数呼び出しする
45
- this.doDisplay(); // (修正) 関数呼び出しする
52
+ this.doDisplay(event.target); // (修正) 関数呼び出しする
46
- return true;
53
+ return true;
47
- },
54
+ },
48
55
  };
49
56
 
50
57
  // (修正) 呼び出しコードを後ろに持ってくる
@@ -52,7 +59,7 @@
52
59
  //初期イベント
53
60
  sampleA1.initialEvent();
54
61
  //windowサイズ変更時のイベント等
55
- $(window).on('resize', sampleA1.resizeEvent);
62
+ jQuery(window).on('resize', sampleA1.resizeEvent);
56
63
  ```
57
64
 
58
65
  ## 解決法