インスタンス内において、アロー関数の「this」はインスタンスを参照しない
Vue.jsに限った話ではないが、Vue.jsを触っていて湧いたちょっとした疑問を調べたメモ。
TL;DR
- アロー関数内の
this
は「Vueインスタンスを参照したい」という文脈での使用に適さないのでつかわない。 function
による関数宣言では「インスタンス内のthis
はインスタンスそのもの」なのでVueインスタンスを参照できる。- アロー関数では「呼ばれた場所が
this
」。 - 例えば
computed
のメソッド内のthis
は「computed
のオブジェクト」であり、インスタンスではないので不適。
経緯
Vue.jsに書いてある
算出プロパティ(例 aDouble: () => this.a * 2) を定義するためにアロー関数を使用すべきではないことに注意してください。アロー関数は、this が期待する Vue インスタンスではなく、this.a が undefined になるため、親コンテキストに束縛できないことが理由です。
とか
data プロパティ(例 data: () => { return { a: this.myProp }}) でアロー関数を使用すべきではないことに注意してください。アロー関数は、this が期待する Vue インスタンスではなく、this.myProp が undefined になるため、親コンテキストに束縛できないことが理由です。
これが気になってちゃんと調べた。
解説
Vue.jsを使用する際、「Vueインスタンスのdata
オプションのオブジェクトに入ってる値」を参照して計算することが多々ある。
例えばこんな感じ(Vue.jsより)
var vm = new Vue({ data: { a: 1 }, computed: { // get のみ。必要なのは関数一つだけ aDouble: function () { return this.a * 2 }, // get と set 両方 aPlus: { get: function () { return this.a + 1 }, set: function (v) { this.a = v - 1 } } } }) vm.aPlus // -> 2 vm.aPlus = 3 vm.a // -> 2 vm.aDouble // -> 4
このとき、this.a
は「data
オプションのオブジェクトのプロパティ名a
」をさしている。
これは、「コンストラクタを呼び出してインスタンスを生成したとき、インスタンス中のthis
はインスタンスそのものをさす」ことによる。
data
、method
などのオプションのオブジェクトのプロパティは、Vueインスタンス直下に格納されるので、this.a
のようにして参照できる。
ちなみに、所属するオプションを明示的にしてアクセスをする場合、this._data.a
だったりthis.$data.a
だったりでアクセスできる。
(ただし、アクセスできるものの、「完全に代替できる」とはいえないっぽいということがオプション / データ - Vue.jsに書いてある。
使用する際は一読することを推奨する。)
では、アロー関数でのthis
はどうなのか。
アロー関数のthis
は、function
の時のように「インスタンス内ではそのインスタンスをさす」という動きはしない。
以下は先ほどの例をただアロー関数に変えたもの。
var vm = new Vue({ data: { a: 1 }, computed: { // get のみ。必要なのは関数一つだけ aDouble: () => { return this.a * 2 }, // get と set 両方 aPlus: { get: () => { return this.a + 1 }, set: (v) => { this.a = v - 1 } } } })
ここで、一部分に着目
var vm = new Vue({ data: { a: 1 }, computed: { aDouble: () => { return this.a * 2 }, } })
このとき、funciton
ではthis.a
はdata
オプションのa
を参照できていた。
しかし、アロー関数を用いるとそうはできない。なぜなら、アロー関数は「呼び出された場所をthisとする」という動きをするからだ。
「呼び出された場所」は今回のケースだと、「computed
オプションのオブジェクト」にあたる。
そのオブジェクトの中にa
をプロパティ名として持つ要素は存在しないので、undefined
となる。
これが、
アロー関数は、this が期待する Vue インスタンスではなく
という文章の意味だった。たしかにVueインスタンスを参照できていないので不適だ。
this
使ってない場合はアロー関数でも問題はないが、混合させるくらいならfunction
で統一すべきだろう。
関連
アロー関数がどうのこうのと言う前に、そもそもthisは結構文脈によってさすものが違うので注意。 JavaScriptの「this」は「4種類」?? - Qiita