Vue.jsのドキュメント書いてある
#computed
算出プロパティ(例 aDouble: () => this.a * 2) を定義するためにアロー関数を使用すべきではないことに注意してください。アロー関数は、this が期待する Vue インスタンスではなく、this.a が undefined になるため、親コンテキストに束縛できないことが理由です。
とか
#data
data プロパティ(例 data: () => { return { a: this.myProp }}) でアロー関数を使用すべきではないことに注意してください。アロー関数は、this が期待する Vue インスタンスではなく、this.myProp が undefined になるため、親コンテキストに束縛できないことが理由です。
が見ていて気になったので、this
についての復習も兼ねて調べてみました。
###アロー関数式とは
そもそもアロー関数式とは?
ES2015(ES6)から利用可能になった新しいJavaScriptの構文の一つ。
ES6とは、2015年に標準として策定されたJavaScriptの新しい文法です。
簡単に言うと、アロー関数は関数リテラルをシンプルに記述する方法!
###記述方法
var vm = new Vue({
data: { a: 1 },
computed: {
aPlus: {
get: () => {
return this.a + 1
},
set: (v) => {
this.a = v - 1
}
}
}
})
上記の例ではfunctionの代わりに=>
が使われていますね。
アロー関数は基本的に以下の様に書きます
// 従来の関数式
function(){};
// アロー関数
() => {};
###特徴
通常の無名関数との違い
-
this
の扱いが違う -
arguments
オブジェクトを持たない - コンストラクタとして振る舞うことはできない
###thisの復習
アロー関数では、this
の挙動も従来の関数とは異なります。→ これが最大の特徴
それについて述べる前にまず、これまでのthis
の挙動がどのようなものであったかを復習!
function show() {
console.log(this);
this.value = 1; // thisはグローバルオブジェクトを指す(※valueはグローバル変数になる)
}
/*グローバルスコープ内*/
show(); // thisはグローバルオブジェクトをさす
this
は、グローバルスコープで呼び出された場合はグローバルオブジェクトを指します。
var obj = {
value: 10,
show: function() {
console.log(this.value); // thisは呼び出されたオブジェクトを指す
}
}
obj.show(); // 10
オブジェクトのメソッドのなかで呼びされた場合はそのオブジェクトを指します。
メソッドにおいても同様で、そのメソッドにアクセスしたオブジェクト(インスタンス)が、this
になります。
function obj(value) {
this.value = value;
this.increment = function() {
this.value++;
};
}
// インスタンス生成
var obj = new obj(0);
console.log(obj.value); // 0
obj.increment();
console.log(obj.value); // 1
コンストラクタとして関数を使った場合、
つまりnew演算子でインスタンスを作った場合は、コンストラクタのなかにあるthis
は、生成されるインスタンスのことを指します。
※new
をつけなかった場合は関数呼び出しになるので、this
はグローバルオブジェクトを指してしまう。
var obj1 = {
value: 1,
show: function() {
console.log(this.value);
}
};
var obj2 = {
value: 3
};
obj1.show(); // 1
obj1.show.apply(obj2); // 3
obj1.show.call(obj2); // 3
let bindFunc = obj1.show.bind(obj2);
bindFunc(); // 3
call
,apply
,bind
これらのメソッドを使うことで、this
となるオブジェクトを指定することができます。
thisの最大の特徴は、それが何を指し示すかは文脈によって変化するということ。
###アロー関数におけるthis
長々と説明しましたが、アロー関数におけるthis
は
**「文脈に依存せず、宣言された時点で、thisを確定(=束縛)する」**これが、アロー関数最大の特徴!
具体的には、定義しているスコープのthis
を引き継ぐことになります。
これによってvar self = this;
みたいなthis
を別の変数で持っておく手法を使わなくて済みます。
###注意点
var vm = new Vue({
data: { a: 1 },
computed: {
aDouble: () => {
return this.a * 2 // アロー関数におけるthis
}
}
})
console.log(vm.aDouble); // NaN
なので注意しなければいけないのが、アロー関数のthis
は、
functionの時のようにインスタンス内ではそのインスタンスを指すという動きはしません。
なぜなら、アロー関数は呼び出された場所をthisとするという動きをするからです。
呼び出された場所は上記のケースだと、this
はcomputed
オプションのオブジェクトにあたります。
よって、computed
オプションのオブジェクトの中にはa
をプロパティ名として持つ要素は存在しないので、this.a
はundefined
となるというわけです。
つまり、これが
アロー関数は、this が期待する Vue インスタンスではなく・・・
という文章の意味だったわけです。Vueインスタンスを参照できないことには注意が必要ですね。
###まとめ
Vue.jsやらのフレームワークを使っていると、
this
があちらこちら散らばって何がなんやらという状態になりやすい気がします。
アロー関数を使って関数部分をシンプルに記述することができればコードの見通しも良くなるのですが、アロー関数内でのthis
は動きが違うので注意が必要です。
###参考文献
インスタンス内において、アロー関数の「this」はインスタンスを参照しない
JavaScriptの「this」は「4種類」??