Javascriptにおける ”this” とは?


はじめに

Reactやコンポーネント思考を利用するには必須といっていいほどの"this"について何となくでいつも使ってましたが、今回しらべるふと意味を調べられずにはいられなくなったので備忘録として残したいと思います。
*内容に不備や言葉足らずなところがあるかと思いますがご了承ください。

thisとは?

"this"ってなんだ?
みんな大好きWeblio辞書で調べてみました。

主な意味:
この、ここの、こちらの、こういう、(たった)今の、現在の、今…、当…、ある(一人の)
(空間的,時間的,心理的に話し手の近くにある対象を指す)
引用 : https://ejje.weblio.jp/content/this

ほぉ~・・・だよね。って思いましたがカッコ内にある内容がJavascriptととしての"this"の意味合いと
マッチしており(注:個人的主観)おおおおおおっ!となりました!!

Javascriptとしての"this"

では早速本編に入っていきます。

下のコードを見てください。
特に何の変哲もない一般的なオブジェクト宣言とその呼び出しになります。

this.js
const dog = {
  value: 'ブルドック',
  voice() {
    console.log(this);
    console.log(this.value);
  }
}
dog.voice();

dogオブジェクトの中にvalue変数とvoiceメソッドが定義されています。
voiceメッソドにはthisの中身とthisプロパティのvalueを表示するようにしています。
この実行結果が下記になります。

result
{
  value: "ブルドック",
  voice: voice() {
    console.log(this);
    console.log(this.value);
  }
}
"ブルドック"

thisの中身を見たときにおお。。。dogオブジェクトそのままやん!!!!
そのとき最初に調べた"this"の意味と一致したのです。
まさにthisを指定した一空間を表示しているではありませんか!!!

(空間的,時間的,心理的に話し手の近くにある対象を指す)

ではさらに次のコードを見てみてください。
dogオブジェクトをanimalオブジェクトでラップしcatオブジェクトを追加しています。
それで再度実行した結果も併せてみてみましょう。

this.js
const animal = {
  dog: {
    value: 'ブルドック',
    voice() {
      console.log(this);
      console.log(this.value);
    }
  }
  cat: {
    value: 'ペルシャ',
    voice() {
      console.log(this);
      console.log(this.value);
    }
  }
}

animal.dog.voice();
result
{
  value: "ブルドック",
  voice: voice() {
    console.log(this);
    console.log(this.value);
  }
}
"ブルドック"

おお?さっきと実行結果が同じ?しかも同空間にあるはずのcatオブジェクトが含まれていませんでした。
この結果から分かるようにthisが指定された全範囲をスコープとするわけではなく、
thisが指定された一階層上の範囲まで効力が及ぶようになっているみたいです。

小難しい話編

一旦ここまでで大まかなthisについての説明は完了となります。
ここからは少し細かな話になります。

グローバル変数としての”this”

定義したオブジェクトをよくグローバル変数として別定義して利用することもあるかと思いますが、
その場合の"this"についても見ていきましょう。
結論から言うと、”this”は元のオブジェクトを参照するのではなくグローバルオブジェクト(ブラウザであればWindowオブジェクト)を参照するようになっています。

this.js
const dog = {
  value: 'ブルドック',
  voice() {
    console.log(this);
    console.log(this.value);
  }
}

const glDog = dog.voice;
glDog();
result
[object Window] {
  addEventListener: function addEventListener() { [native code] },
~~~~中略~~~~~
  },
  window: [circular object Window]
}
undefined

先に述べたように変数に代入して利用した場合は、グローバルオブジェクトを参照するためdogオブジェクト内に定義してあるvalue値呼ばれずグローバルオブジェクトのvalue値を呼びに行こうとしてundefinedとして返されます。
(もちろんグローバルオブジェクト内にはvalueなんてものはないのでundefinedですねwww)

もし変数として利用したい場合にはオブジェクトごと変数へと代入して利用することができます。
下記の通りです。

this.js
const dog = {
  value: 'ブルドック',
  voice() {
    console.log(this);
    console.log(this.value);
  }
}

const glDog = dog;
glDog.voice();
result
{
  value: "ブルドック",
  voice: voice() {
    console.log(this);
    console.log(this.value);
  }
}
"ブルドッグ"

んーーー、こんなことしてまで別だしして使う必要もないかと思いますがこんな感じです。

まとめ

一旦こんな感じでthisについてまとめてみましたがいかがでしたでしょうか?
もやもやしながら使っていたものが理解しながら利用することで実装のヒントとして利用することができるかもしれません。
次回は"this"に最もかかわりの深い"bind"について投稿できればなと思っています!
ご閲覧ありがとうございました!!!

参考文献

【初心者向け】JavaScriptのbindって何??を理解する(call, appyも一緒に)