回答編集履歴
3
CoffeeScriptの余計なセミコロンを削除
answer
CHANGED
@@ -139,6 +139,6 @@
|
|
139
139
|
if this.count > 0
|
140
140
|
this.count--
|
141
141
|
setTimeout(this.countDown, 1000)
|
142
|
-
ct = new CountSec(10)
|
142
|
+
ct = new CountSec(10)
|
143
|
-
ct.countDown()
|
143
|
+
ct.countDown()
|
144
144
|
```
|
2
細かい表現の修正
answer
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
`method1`は通常の書き方です。`method2`は、2018年3月3日現在、仕様候補(stage 3)として提案中である[Class field declarations(クラスフィールド宣言)](https://github.com/tc39/proposal-class-fields)を用いた書き方です。**まだ、仕様には含まれておらず、また、このまま仕様に含まれること
|
1
|
+
`method1`は通常の書き方です。`method2`は、2018年3月3日現在、仕様候補(stage 3)として提案中である[Class field declarations(クラスフィールド宣言)](https://github.com/tc39/proposal-class-fields)を用いた書き方です。**まだ、仕様には含まれておらず、また、このまま仕様に含まれることが確定されたわけではありません。**Babelでのトランスパイルは対応していますが、ブラウザでは対応している物が一つもありません。
|
2
2
|
|
3
3
|
さて、`method2`ですが、これはインスタンスメソッドの定義と言うより、インスタンス変数の定義です。現在のECMAScriptではclassの内側にメソッド以外は直接書くことができません。そこで、Javaのような他の言語のように、インスタンス変数も宣言できるようにしたのがクラスフィールド宣言になります。このクラスフィールド宣言により、インスタンス作成時に、そのインスタンス変数がプロパティとして作成されます。また、宣言と共に初期化子(代入演算子`=`と右辺のこと、これ自体はオプション)があれば、その値で初期化されるとなります。
|
4
4
|
|
1
誤字の修正
answer
CHANGED
@@ -36,7 +36,7 @@
|
|
36
36
|
ct.countDown();
|
37
37
|
```
|
38
38
|
|
39
|
-
指定された回数分だけ1秒毎(あまり正確ではない)にカウントダウンするという意図のコードです。**このコードはこのままでは正常に動作しません。**二回目の`countDown`の呼び出しでは`this`がそのインスタンスではなくなるからです。これはアロー関数や`bind`
|
39
|
+
指定された回数分だけ1秒毎(あまり正確ではない)にカウントダウンするという意図のコードです。**このコードはこのままでは正常に動作しません。**二回目の`countDown`の呼び出しでは`this`がそのインスタンスではなくなるからです。これはアロー関数や`bind`等で`this`が束縛されていない関数がコールバック等で呼び出されるとき、`this`は呼び出し側の関数に依存することに起因します。いわゆる`this`問題というものです。これを現在のECMAScript 2017で修正する方法は三つです。
|
40
40
|
|
41
41
|
一つ目は、アロー関数で囲むことです。アロー関数は評価時に`this`を束縛することができますので、コールバックでの呼び出し時も`this`が変わることはありません。
|
42
42
|
|
@@ -98,7 +98,7 @@
|
|
98
98
|
ct.countDown();
|
99
99
|
```
|
100
100
|
|
101
|
-
これらの方法は、いずれも初めのコードよりは冗長です。よく読めば意味がわからないわけではありませんが、なぜそんなことをするのかという意図がつかみにくいです。ましてや、一つ目と二つ目は毎回関数生成、三つ目は`bind`の位置とメソッド定義位置が離れてしまうことを考えると、あまり良い方法とは言えません。
|
101
|
+
これらの方法は、いずれも初めのコードよりは冗長です。よく読めば意味がわからないわけではありませんが、なぜそんなことをするのかという意図がつかみにくいです。ましてや、一つ目と二つ目は毎回関数が生成されること、三つ目は`bind`の位置とメソッド定義位置が離れてしまうことを考えると、あまり良い方法とは言えません。
|
102
102
|
|
103
103
|
そこで考えられたのがクラスフィールド宣言を使う方法です。これを使った場合は次のように書けます。
|
104
104
|
|
@@ -121,7 +121,7 @@
|
|
121
121
|
|
122
122
|
`countDown`は親であるprototypeに登録されるようなメソッドではなく、インスタンス変数ではありますが、`this`を束縛すると言うことはそのインスタンス専用になっている事であり、そこは問題にはなりません。`this`の束縛があるという違い以外は通常のメソッドと同様に使えます。最初の三つのコードのような問題もありません。
|
123
123
|
|
124
|
-
さて、この方法を使う機会が思いつかないという人が居るかも知れませんが、使う会が多いものを知っていますので、紹介します。それはReactです。[Handling Events - React](https://reactjs.org/docs/handling-events.html)にその実例が載っています。Reactではクリックなどのイベント発生時に呼び出す関数を登録するのですが、そのまま`this.handelEvent`と書いてしまうと同じ問題が発生します。それを防ぐ手段として、クラスフィールド宣言は有効とされています。Reactを使う場合、いずれにしてもJSXのた
|
124
|
+
さて、この方法を使う機会が思いつかないという人が居るかも知れませんが、使う機会が多いものを知っていますので、紹介します。それはReactです。[Handling Events - React](https://reactjs.org/docs/handling-events.html)にその実例が載っています。Reactではクリックなどのイベント発生時に呼び出す関数を登録するのですが、そのまま`this.handelEvent`等と書いてしまうと同じ問題が発生します。それを防ぐ手段として、クラスフィールド宣言は有効とされています。Reactを使う場合、いずれにしてもJSXのためにBabelをつかいますから、Babelが対応しているクラスフィールド宣言を使ってもさほど問題が無いと考えられます。
|
125
125
|
|
126
126
|
最後に、通常とのメソッドとの違いです。一番大きいのは、このクラスフィールド宣言ではインスタンスが生成させる度にそのインスタンス変数としての関数が生成されると言うことです。そのため、本当に必要であるという場合以外は使用すべきではないでしょう。
|
127
127
|
|