よくでてくるJavaScriptのthisの使い分けについて自分なりに使用されるケースを踏まえて分類してみようと思います。
- グローバル
- オブジェクト内
- イベントハンドラ内(jQueryなどでよく使われる)
- apply, call, bindによる強制
- アロー関数による変更
グローバル
呼び出し元がオブジェクトでない場合、グローバルオブジェクト、つまりwindowオブジェクトを指します。関数パターンなどと呼ばれているものです。
function test() {
console.log(this); // window (strictモードではundefined)
}
test();
オブジェクト内
オブジェクトで定義されている場合、オブジェクト自身を指します。メソッドパターンやコンストラクタパターンです。
const obj = {
name: '太郎',
greet() {
console.log(this.name); // '太郎'
}
};
obj.greet();
// ES6クラスでインスタンス作成
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(this.name);
}
}
const hanako = new User('花子');
hanako.greet(); //'花子'
イベントハンドラ内
jQueryなどでよく使われるパターンです。この場合、thisの参照先はイベントが発生した要素自身を指します。
// 通常の関数
$('button').click(function() {
console.log(this); // クリックされたbutton要素
$(this).addClass('clicked');
});
apply, call, bindによる強制
参考書ではよく出てきますが、一番難しいです。参照先を変えたいときに使います。
const person = { name: '花子' };
function sayName() {
console.log(this.name);
}
sayName.call(person); // '花子'
// bindは関数を返す
const boundSayName = sayName.bind(person);
boundSayName(); // '花子'
アロー関数による変更
注意点として、アロー関数を使うとthisの参照先が変わります。 アロー関数は定義された場所のthisを継承します(レキシカルスコープ)。
// 通常の関数
$(セレクタ).click(function() {
// 自分自身(クリックされた要素)
$(this);
});
// アロー関数
$(セレクタ).click(() => {
// 外側のオブジェクト
this.〜;
// もし自分自身を参照したいときは$(event.currentTarget)と書きます。
});
実用例:
const obj = {
name: '太郎',
normalFunc: function() {
setTimeout(function() {
console.log(this.name); // undefined (thisはwindow)
}, 100);
},
arrowFunc: function() {
setTimeout(() => {
console.log(this.name); // '太郎' (thisはobj)
}, 100);
}
};
ES6でクラスを書いていて親クラスを呼びたいとき、メソッド内でアロー関数を使わないとthisが期待通りにならないケースがあるので注意が必要です。
参考リンク
色々とわかりやすい解説がありますが、やはり実際にコードを書いて格闘しないと本当の理解は難しいですね。