LoginSignup
29
30

More than 3 years have passed since last update.

JavaScriptのthisとPHPのthis

Last updated at Posted at 2020-03-20

どんな記事?

JavaScriptとPHPのthisを比べながら理解しよう。

背景

thisがよく分からん!

JavaScriptのthis他の言語と少々異なる動作をするらしい

よろしい、ならば比較だ

PHPのthis

PHPの疑似変数である$thisは、メソッドがオブジェクトコンテキストからコール場合に利用することができる。
$thisは呼び出し元オブジェクトへの参照である。

カレントオブジェクトからそのクラス内の関数や変数にアクセスする場合に$thisを使える。

(コンテキストは直訳だと文脈という意味。
プログラミング用語的には、背景となる情報という言い回しが妥当かな?)

(カレントオブジェクトとは、インスタンスメソッドが起動されたオブジェクトのこと)

<?php
//クラス(Sample)
class Sample
{
  //プロパティ($hoge)宣言
  public $hoge = 'foo';

  //メソッド(display)宣言
  public function display()
  {
    //displayメソッドで$hogeの内容を呼び出す
    echo $this->$hoge;
  }
}

$sample = new Sample;
$sample->display(); //出力結果:foo
?>

なぜ$thisが必要か?

それは、
クラス定義の内部では、それにアクセス可能なオブジェクト名を知ることができない
からである。
上記サンプルでは、Sampleクラスが書かれている時点では、
そのオブジェクトの名前があとで$sampleになるのか、はたまた$showになるのか分からない。

その為、Sampleクラスの中で

$sample->$hoge

と書くことはできないのである。

代わりに、クラスの中から、そのクラス内の関数や変数にアクセスする為に$thisを使う。

JavaScriptのthis

ほとんどの場合、thisの値は、関数の呼ばれ方によって決定されます。これは実行時に割り当てできず、関数が呼び出されるたびに異なる可能性があります。

ほう。

構文

this

値:現在のコードが実行されているJavaScriptコンテキストオブジェクトです

グローバルコンテキスト

JavaScriptにおけるグローバル実行コンテキスト(いずれかの関数の外側)では、
thisはグローバルオブジェクトを参照する。

例文
//whidowはグローバルオブジェクト
//thisはグローバルオブジェクトを示す
console.log(this === window);  // true

//グローバルオブジェクトで宣言
this.hoge = 37;
//windowグローバルオブジェクトから
//thisで宣言した値を呼び出すことができる
console.log(window.hoge); //出力結果:37

あれ、PHPとぜんぜん違いますね(驚愕)

関数コンテキスト

単純な呼び出し

次の例は呼び出し時にthisの値がセットされない為、thisはデフォルトでグローバルオブジェクトとなり、それはブラウザではwindowと同等である。

funcion f1() {
  return this;
}

f1() === window; //出力結果:true

別のコンテキストからthisの値を呼び出す場合はcallもしくはapplyを使用する。

//オブジェクト定義
var obj = {a: 'Custom'};

function whatsThis() {
  return this.a;
}

whatsThis.call(obj); //出力結果:Custom

アロー関数

アロー関数では、thisはそれを囲むレキシカル(静的)なコンテキストのthisの値が設定される。

var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); //出力結果:true

オブジェクトのメソッドとして

関数がオブジェクトのメソッドとして呼び出される時、そのthisにはメソッドが呼び出されたオブジェクトが設定される。

次の例ではtest.func()が起動した時、関数内のthisにはtestオブジェクトが関連付けられる。

const test = {
  prop: 42,
  func: function () {
    retrun this.prop;
  },
};

console.log(test.func());
//出力結果: 42

この振る舞いは、関数定義の方法や場所に全く影響を受けない。

オブジェクトのプロトタイプチェーン上のthis

同じ概念が、オブジェクトのプロトタイプチェーンのどこかに定義されたメソッドにもあてはまる。
そのメソッドがオブジェクト上にあるかのように、thisはメソッドを呼び出したオブジェクトを参照する。

var o = {
  f: function() {
    return this.a + this.b
  }
}
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); //出力結果:5

コンストラクタとして

関数がコンストラクタとして(newで生成される)使用される時、そのthisは生成された新しいオブジェクトにバインド(拘束)される

//関数定義
function C() {
  this.a = 37;
}
//コンストラクタ生成
var o = new C();
console.log(o.a); //出力結果:37

DOMイベントハンドラとして

関数がイベントハンドラとして使用される場合、そのthisにはイベントを発火させた要素が設定される

//要素を青色にする関数
function bluify(e) {
  console.log(this === e.currentTarget);
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}
//全ての要素を取得
var elements = document.getElementByTagName('*');
//クリックリスナーとしてbluify関数を設定
//クリックした要素が青色に変わる
for(var i = 0; i < elements.length; i++){
  elements[i].addEventListener('click', bluify, false);
}

比べてみて

JavaScriptのthisは、オブジェクトのメソッドコンストラクトとして使うのであればPHPと同じような理解でいいのかな、と思いました。
DOMイベントハンドラとしてはフロントエンドならでは、という感じですね。

グローバルコンテキスト・関数コンテキストでのthisは、まだ使い道が分からん...

参考

PHP: クラスの基礎 - Manual
PHPで擬似変数$thisって何のためにあるのか?
this - JavaScript|MDN
「コンテキスト」という言葉が何を指しているのかよく分からない
レキシカルスコープとクロージャを理解する

29
30
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
30