はじめに
今回はJavaScriptの闇... thisについて、様々な角度で挑みたいと思います!
thisとは
thisは関数の呼び出し元へのリンクです。
例えば、以下の場合test.getName()はtaroを返します。
thisは関数getNameで呼び出されています。その関数getNameはtestオブジェクトの関数なので、this = testオブジェクトになります。
関数getName()のthisをtestオブジェクトに変え、test.name = taroとなります。
const test = {
name: 'taro',
getName: function() {
return this.name;
}
}
グローバルなthis
関数の読み出し元を指定しない場合はWindowになります。
それを確認してみましょう。
以下2つを定義しておきます。
まず、obj.sayThis()を考えます。
sayThis()はobjオブジェクトから呼び出されているので、関数sayThis内のthisはobjオブジェクトになります。
ということで、obj.sayThis()は { name: 'taro' } を返します
次に、sayThis()を考えます。
こちらは特に呼び出しているオブジェクトがないため、Windowになります。
ちなみに、strictモードで実行すると、undefinedになります。
// メソッド
const sayThis = function() { console.log(this) }
// オブジェクト
const obj = { name: 'taro' }
コンストラクタでのthis
コンストラクタではnewでオブジェクトを作成でき、呼び出し元が定まります。
以下のように定義しておきます。
yamadaの方ではnew Personによりオブジェクトが作成されるので、yamada.nameはtaroを返します。
しかし、tanakaの方はオブジェクトが作成されていないので、name of undefinedエラーになります。
const Person = function(hoge) { this.name = hoge; }
const yamada = new Person('taro')
const tanaka = Person('taro')
プロトタイプメソッド内でのthis
以下のように定義しておきます。
ここで、yamada.getName()とすると、taroが返ります。
ちなみに、Person.getName()の場合はPerson.getName is not a functionになります。
const Person = function(hoge) { this.name = hoge; }
Person.prototype.getName = function() { return this.name; }
const yamada = new Person('taro')
対して、次のようにprototypeをなくした場合は、yamada.getName is not a functionになります。
また、Person.getName()の場合、Personが返ります。
const Person = function(hoge) { this.name = hoge; }
Person.getName = function() { return this.name }
const yamada = new Person('taro')
入れ子関数でのthis
入れ子関数にすると、定義元はどうなるでしょう。
以下を定義して、test.sayHello()を実行すると、上から { sayHello: f }, Windowになります。
最初のthisの呼び出し元はsayHelloで、2番目のthisは呼び出し元が明示されていないためです。
const test = {
sayHello: function() {
console.log(this)
const func = function() {
console.log(this)
}
func()
}
}
arrow関数でのthis
入れ子関数でもarrow関数にすると、thisの呼び出し元が定まります。
そのため以下の場合、test.sayHello()は、{ sayHello: f }, { sayHello: f } になります。
const test = {
sayHello: function() {
console.log(this)
const func = () => {
console.log(this)
}
func()
}
}
まとめ
今回はJavaScriptで迷いやすいthisについて解説していきました!
なるほど分からんと思った方、ぜひコンソール画面などで遊んでみてください!