thisの使い方

thisは一般的に関数内で使われ、関数の呼び出し方によって何を示すか変わってきます。

本ページでは、thisの使い方を説明します。

thisが何を示すのか?

thisは、呼び出し元のオブジェクトを示します。例えば、あるオブジェクトのメソッドとして呼び出した関数内で使うと、thisの中身はそのオブジェクトになります。

thisの説明

また、呼び出し元が異なるオブジェクトを指定することもあります。

つまり、呼び出し元や使い方によって、thisが何を示すのかは変わるということです。

thisには、以下のような使い方があります。

次からは、それぞれの使い方を説明します。

また、最後にthisを使うメリットについても説明しています。

グローバル実行コンテキストで呼び出す

グローバル実行コンテキストとは、関数の外側を意味します。

以下のように、thisをグローバル実行コンテキストで実行したとします。

【グローバル実行コンテキストでthisを実行する例】
var x = 1;
alert(this.x);

上記の例は、alert(x);と記述したのと同じで1が表示されます。

thisは、グローバル実行コンテキストではwindowオブジェクトを示します。このため、this.xはwindow.xです。windowオブジェクトは、ブラウザで表示した時に最初から存在し、グローバルオブジェクトと呼ばれます。

varで宣言したxは、windowオブジェクトのプロパティとして存在するグローバル変数です。したがって、グローバル変数xはwindow.xとも書けます。つまり、this.xとグローバル変数xは同じwindow.xです。

関数コンテキストで実行する

関数コンテキストとは、関数の内側を意味します。

以下のように、thisを関数コンテキストで実行したとします。

【関数コンテキスト(非Sctictモード)でthisを実行する例】
function func1() {
  alert(this.x);
}

var x = 1;
func1();

上記は、グローバル実行コンテキストで実行した時と同じです。this.xはwindows.xと同じになります。ただし、これは非Strictモードで実行した時です。

以下のように、Sctictモード(厳格モード)で実行したとします。

【関数コンテキスト(Sctictモード)でthisを実行する例】
function func1() {
  'use strict';
  alert(this.x);
}

var x = 1;
func1();

'use strict'でSctictモードにしています。Strictモードは、非Strictモードではエラーにならないコードでも、悪影響を与える可能性がある場合はエラーにしたりします。

上記の場合、thisがundefinedとなり、エラーになります。これは、func1が直接呼び出されているためです。window.func1()で呼び出せば、this.xは1になります。

メソッドで呼び出す

オブジェクトのメソッドで呼び出した場合のthis利用例です。

【オブジェクトのメソッドとして呼び出した場合のthis利用例】
const yamada = {
  address: "Tokyo",
  display: function() {
    alert("住所は" + this.address + "です。");
  }
};
yamada.display();

最後のyamada.display()で、displayがyamadaオブジェクトのメソッドとして呼び出されています。このため、thisはyamadaオブジェクトを示します。つまり、this.addressはyamada.addressを示すことになり、結果として「住所はTokyoです。」と表示されます。

グローバル実行コンテキストや直接関数を呼び出すとthisはwindowオブジェクトを示しましたが、この例のようにオブジェクトのメソッドとして呼び出すとthisはそのオブジェクトを示すようになります。

イベントハンドラーで呼び出す

イベントハンドラーで呼び出した場合のthis利用例です。

【イベントハンドラーとして呼び出した場合のthis利用例】
<p id="dom-test">これはテストです。</p>

<script>
function func1() {
  this.style.color = "red";
}

const x = document.querySelector("#dom-test");
x.addEventListener("click", func1, false);
</script>

最後のイベントリスナー(x.addEventListener)で、要素がクリックされるとイベントハンドラーのfunc1が呼び出されます。この時のthisは、id:dom-testの要素オブジェクトを示します。したがって、要素がクリックされると、クリックした要素の文字が赤に変わります。

コンストラクタ関数で呼び出す

コンストラクタ関数で呼び出した場合のthis利用例です。

【コンストラクタ関数として呼び出した場合のthis利用例】
function Peaple(address) {
  this.address = address;
}

const yamada = new Peaple("Tokyo");

最後の行で、Peapleがyamadaオブジェクトのコンストラクタとして呼び出されています。この時、コンストラクタ関数内のthisは、yamadaオブジェクトを示します。したがって、this.addressは、yamada.addressプロパティを作成することになります。

なお、コンストラクタ関数については、オブジェクトの作り方をご参照ください。

callメソッドを使う

thisがオブジェクトを示すと言っても、以下はthis.addressがundefinedになります。

【直接関数を呼び出した時のthis】
function display() {
  alert("住所は" + this.address + "です。");
}

const yamada = {
  address: "Tokyo",
};
display();

最後のdisplay()がオブジェクトのメソッドではなく、直接実行されています。このため、thisがwindowオブジェクトを示し、this.addressはaddress変数(window.address)と同じになります。address変数は宣言されていないため、undefinedになります。

もし、thisをyamadaオブジェクトにしたい場合は、callメソッドを使います。

【callメソッドの利用例】
function display() {
  alert("住所は" + this.address + "です。");
}

const yamada = {
  address: "Tokyo",
};
display.call(yamada);

callメソッドを使うと、thisで示すオブジェクトを指定できます。上記例では、thisがyamadaオブジェクトを示すことになるため、this.addressはTokyoになります。

callメソッドでは、引数も渡せます。

【callメソッドでの引数利用例】
function display(x,y) {
  alert(x + this.address + y);
}

const yamada = {
  address: "Tokyo",
};
display.call(yamada,"住所は","です。");

引数は、「住所は」と「です。」です。xとyで受け取っているため、結果として「住所はTokyoです。」と表示されます。

applyメソッドを使う

callメソッドの代わりに、applyメソッドを使うと、引数を配列で渡せます。

【applyメソッドの利用例】
function display(x,y) {
  alert(x + this.address + y);
}

const yamada = {
  address: "Tokyo",
};
const z = ["住所は","です。"];
display.apply(yamada,z);

最後の行(display.apply)で配列で引数を渡し、xyで受け取っています。結果として、「住所はTokyoです。」と表示されます。

引数の数は、関数の使い方で説明した残余引数やargumentsを利用して、可変にすることもできます。

bindメソッドを使う

以下のスクリプトがあったとします。

【グローバル変数が結果となる例】
const z = {
  x: 20,
  display: function() {
    alert(this.x);
  }
};

var x = 10;
const y = z.display;
y();

最後のy()は、直接実行されているためthisがwindowを示し、this.xは変数xとなります。つまり、オブジェクトzのプロパティxは20ですが、結果としてwindow.xを示すことになって10が表示されます。

もし、this.xをオブジェクトzのプロパティxにしたい場合は、bindメソッドが使えます。

【bindメソッドの利用例】
const z = {
  x: 20,
  display: function() {
    alert(this.x);
  }
};

var x = 10;
const y = z.display.bind(z);
y();

変えたのは、bind(z)部分だけです。これで、thisがzオブジェクトを示すようになり、this.xはz.xと同じになります。つまり、結果として20が表示されます。

thisを使うメリット

thisのメリットは、1つのthisで複数のオブジェクトを扱えることです。イベントハンドラーで呼び出すで説明した使い方を、複数の要素オブジェクトに対して使ってみます。

【複数のハンドラーとして呼び出した場合のthis利用例】
<p id="dom-test1">これはテストです。</p>
<p id="dom-test2">これはテストです。</p>

<script>
function func1() {
  this.style.color = "red";
}

const x = document.querySelector("#dom-test1");
const y = document.querySelector("#dom-test2");
x.addEventListener("click", func1, false);
y.addEventListener("click", func1, false);
</script>

赤字から呼び出した時はthisがdom-test1の要素オブジェクト、青字から呼び出した時はthisがdom-test2の要素オブジェクトを示すため、それぞれの要素オブジェクトをクリックすると赤に変わります。つまり、不特定多数のオブジェクトから呼び出されても、1つの記述(この例ではfunc1という1つの関数だけ)で各オブジェクトに対して操作が可能です。

もう1つの例です。

【複数のインスタンスで利用するthis利用例】
function Peaple(address) {
  this.address = address;
}

const yamada = new Peaple("Tokyo");
const suzuki = new Peaple("Kyoto");

yamadaでもsuzukiでもコンストラクタを呼び出すと、thisはそれぞれのオブジェクトを示すため、1つのコンストラクタで複数のインスタンスが作成できます。