初めに
普段Node.jsを使用しており、通常関数のthisの基本的な仕様を勉強したためアウトプットのために記事を投稿する。
開発環境
■ Node.jsのバージョン
v11.1.0
■ 使用OS
Amazon Lunux 2
① 基本的な例
const o = {
name: 'taro',
introduce() { return `My name is ${this.name}`; }
}
console.log(o);
console.log(o.introduce());
上記コードでは、oという定数にオブジェクトが格納されている。
以下は参考文献[1]より抽出したもの。
メソッドが呼び出されるときthisは、そのメソッドがプロパティとなっているオブジェクトを指しています。
こちらを拝借すると、ここで指しているメソッドとは以下にあたる。
introduce()
そして、メソッドがプロパティとなっているオブジェクトとは定数oである。
そのため、thisはoをバインドするため以下に置き換えられる。
this.name
↓
o.name
よって出力結果は以下となる。
{ name: 'taro', introduce: [Function: introduce] }
My name is taro
②オブジェクトのプロパティを代入した例
const o = {
name: 'taro',
introduce() { return `My name is ${this.name}`; }
}
const introduce= o.introduce;
console.log(introduce=== o.introduce);
console.log(introduce());
console.log(o.introduce());
今回は、オブジェクトのプロパティを定数introduceに代入している。
出力結果は以下となる。
true
My name is undefined
My name is taro
代入した定数では、結果がundefinedとなっている。
これは、プロパティとなっているオブジェクトを特定できないため、thisがundefinedになっている。
③ 関数が入れ子になっている場合
const o = {
name: 'taro',
external() {
console.log(this.name);
function internal() {
console.log(this.name);
}
internal();
},
};
o.external();
出力結果
taro
undefined
この場合、externalメソッドのthisは定数oをバインドしているが、internal関数内のthisは何もバインドしていない。
以下は参考文献[2]より抽出したもの。
ほとんどの場合、this の値はどのように関数が呼ばれたかによって決定されます (実行時結合)。これは実行時に代入によって設定することはできず、関数が呼び出されるたびに異なる可能性があります。
通常の関数では呼び出し方によってthisのバインド先が変わることが分かる。
internal関数の呼び出しはexternalメソッドで行っているため、thisがundefinedとなっている。
この問題は以下のような解決策がある。
const o = {
name: 'taro',
external () {
let self = this;
console.log(this.name);
function internal() {
console.log(self.name);
}
internal();
},
};
o.external();
externalメソッドのthisをselfという変数に代入して、undefinedとなっていたinternal関数内で使用している。
参考文献を確認すると、bind() メソッドやアロー関数等でthisのバインド先を変更できるようだが、上記コードのような解決方法も使用できる。