はじめに
コードを書いている中で、 this
を度々使っているでしょう。
そのときちゃんと this
の値を意識できていますか?
その値の違いをまとめていきます。
参考資料
thisの値
無名関数内
thisの値はレシーバ(左辺)の親になる。
もしもレシーバが存在しない場合は、グローバル( Object [global]
)となる。
main.js
function Test() {
this.field = 'test';
};
Test.prototype.func = function() {
console.log(this);
};
const test = new Test();
test.func();
$ node ./main.js
Test { field: 'test' }
アロー関数内
thisの値はその関数のスコープ内のthisと同じになる。
もしもグローバルスコープで宣言された場合は、空オブジェクト( {}
)となる。
main.js
function Test() {
this.field = 'test';
};
Test.prototype.func = () => {
console.log(this);
};
const test = new Test();
test.func();
$ node ./main.js
{}
クラスのメソッドの中で定義された関数内(ES2015以降の書き方)
無名関数で書いた場合、thisの値はクラスのメソッドの親のスコープとなり、 undefined
が返る。
一方アロー関数で書いた場合、thisの値はクラスのメソッドのスコープとなり、 Test
が返る。
main.js
class Test {
test() {
this.one = '111';
callback(function() {
console.log('anonymous:', this);
});
callback(() => {
console.log('arrow :', this);
});
}
}
const test = new Test();
test.test();
function callback(func) {
func();
}
$ node ./main.js
anonymous: undefined
arrow : Test { one: '111' }
クラスのメソッドの中で定義された関数内(ES2015以前の書き方)
無名関数で書いた場合、thisの値はクラスのメソッドの親のスコープとなり、 Object [global]
が返る。 ES2015以降の書き方を使った場合とは異なる動作をする。
一方アロー関数で書いた場合、thisの値はクラスのメソッドのスコープとなり、 Test
が返る。
main.js
function Test() {};
Test.prototype.test = function() {
callback(function() {
console.log('anonymous:', this);
});
callback(() => {
console.log('arrow :', this);
});
};
const test = new Test();
test.test();
function callback(func) {
func();
}
$ node ./main.js
anonymous: Object [global] { ... }
arrow : Test { one: '111' }
おわりに
this
の内容は、使う場所によって異なります。
そのため、動作をしっかりと押さえておかないと、正しく動作するプログラムを作れません。
よくあるケースとして、こんなものがあることでしょう。
無名関数で記述しているところを一斉にアロー関数に書き換えます。すると、動作しなくなりました。
こういう問題にぶち当たったときは、一度 this
の値に注目してデバッグしてみてください。