this


 this  JavaScript strict 

this  ()ES5  bind()  `this` ES2015  this  ( this )

試してみましょう

構文

this

strict モードでない場合は、実行コンテキスト (グローバル、関数、eval) のプロパティで、常にオブジェクトへの参照です。 strict モードではどのような値でも取り得ます。

解説

グローバルコンテキスト

グローバル実行コンテキスト (すべての関数の外側) では、strict モードであるかどうかにかかわらず、this はグローバルオブジェクトを参照します。

js
// ウェブブラウザーでは window オブジェクトもグローバルオブジェクトです。
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b); // "MDN"
console.log(b); // "MDN"

メモ: コードが実行されている現在のコンテキストに関係なく、グローバルの globalThis プロパティを使用していつでも簡単にグローバルオブジェクトを取得できます。

関数コンテキスト


 this 

 strict  this this  window 
js
function f1() {
  return this;
}

// ブラウザー上で
f1() === window; // true

// Node 上で
f1() === global; // true

ただし strict モードでは、実行コンテキストに入るときに this 値が設定されていないと、以下の例のように undefined のままになります。

js
function f2() {
  "use strict"; // strict モードにする
  return this;
}

f2() === undefined; // true

: this  undefined  f2  ( window.f2())  strict  window 

関数の呼び出し時に this の値を特定の値に設定するには、以下の例のように call() または apply() を使用します。

クラスコンテキスト

クラスは関数の機能であるため、クラスと関数の this の動作は似ています。ただし、いくつかの違いと注意点があります。

クラスのコンストラクター内では、this は通常のオブジェクトです。クラス内のすべて静的でないメソッドは this のプロトタイプに追加されます。

js
class Example {
  constructor() {
    const proto = Object.getPrototypeOf(this);
    console.log(Object.getOwnPropertyNames(proto));
  }
  first() {}
  second() {}
  static third() {}
}

new Example(); // ['constructor', 'first', 'second']

メモ: 静的メソッドは this のプロパティではありません。クラス自身のプロパティです。

派生クラス


 this super()  this Base 
js
this = new Base();

警告: thissuper() の呼び出しの前に参照すると、エラーが発生します。

派生クラスはでは super() を呼び出す前に return をしてはいけません。ただし、 Object を返す場合やコンストラクターがない場合を除きます。

js
class Base {}
class Good extends Base {}
class AlsoGood extends Base {
  constructor() {
    return { a: 5 };
  }
}
class Bad extends Base {
  constructor() {}
}

new Good();
new AlsoGood();
new Bad(); // 参照エラー

関数コンテキスト内の this

js
// オブジェクトを call や apply の最初の引数として渡すと、this がそれに結び付けられます。
var obj = { a: "Custom" };

// 変数を定義すると、その変数がグローバルの window のプロパティとして割り当てられます。
var a = "Global";

function whatsThis() {
  return this.a; // this の値は関数の呼び出し方によって変わります
}

whatsThis(); // 'Global' はこの関数では this として設定されていないので、既定でグローバルの window オブジェクトになります
whatsThis.call(obj); // 'Custom' が関数内の this として obj に設定されています
whatsThis.apply(obj); // 'Custom' が関数内の this として obj に設定されています

this とオブジェクト変換

js
function add(c, d) {
  return this.a + this.b + c + d;
}

var o = { a: 1, b: 3 };

// 最初の引数は 'this' として使用する
// オブジェクトで、続く引数は関数呼び出しの
// 引数として使用されます。
add.call(o, 5, 7); // 16

// 最初の引数は 'this' として使用する
// オブジェクトで、二番目の引数は関数呼び出しの
// 引数として使用される配列です。
add.apply(o, [10, 20]); // 34

なお、 strict モードでない場合、callapply は、this として渡された値がオブジェクトではないと、内部の ToObject 操作を利用してオブジェクトに変換しようします。7'foo' のようなプリミティブが渡された場合、関連するコンストラクターを使用してオブジェクトに変換されます。たとえば、プリミティブの数値である 7new Number(7) であるかのようにオブジェクトに変換され、文字列の 'foo'new String('foo') であるかのようにオブジェクトに変換されます。

js
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
bar.call("foo"); // [object String]
bar.call(undefined); // [object global]

bind メソッド


ECMAScript 5  Function.prototype.bind() f.bind(someObject) f  this 使 bind 
js
function f() {
  return this.a;
}

var g = f.bind({ a: "azerty" });
console.log(g()); // azerty

var h = g.bind({ a: "yoo" }); // bind は一度しか機能しない
console.log(h()); // azerty

var o = { a: 37, f: f, g: g, h: h };
console.log(o.a, o.f(), o.g(), o.h()); // 37,37, azerty, azerty

アロー関数

アロー関数では、this はそれを囲む構文上のコンテキストの this の値が設定されます。グローバルコードでは、グローバルオブジェクトが設定されます。

js
var globalObject = this;
var foo = () => this;
console.log(foo() === globalObject); // true

メモ: アロー関数の呼び出し時に this 引数が call, bind, apply に渡されても無視されます。呼び出しに引数を加えることはできますが、最初の引数 (thisArg) は null を設定してください。

js
// オブジェクトのメソッドとして呼び出す。
var obj = { func: foo };
console.log(obj.func() === globalObject); // true

// call を使用して this の設定を試みる
console.log(foo.call(obj) === globalObject); // true

// bind を使用して this の設定を試みる
foo = foo.bind(obj);
console.log(foo() === globalObject); // true

何があっても、foothis は生成されたときの値が設定されています (上記の例ではグローバルオブジェクトです)。同様のことが、ほかの関数内で生成したアロー関数にも適用されます。それらの this には、それを包含する構文上のコンテキストのものになります。

js
// this を返す関数を返す bar メソッドを持つ
// obj を生成します。返された関数はアロー関数
// として生成されているため、その this は
// それを包含する関数の this に永続的に拘束
// されます。bar の値は呼び出し時に設定でき、
// 返値の関数の値に順に設定します。
var obj = {
  bar: function () {
    var x = () => this;
    returnx;
  },
};

// bar を obj のメソッドとして呼び出す際、その this を obj に設定します
// 返値の関数への参照をfnに割り当てます。
varfn= obj.bar();

// strict モードでは、this を設定せずにfnを呼び出すと
// 通常はグローバルオブジェクトか undefined が既定値となります。
console.log(fn() === obj); // true

// しかし obj のメソッドを call することなく参照するのは要注意です。
var fn2 = obj.bar;
// するとアロー関数の呼び出しで this は bar の
// this に従うため window と同じになります。
console.log(fn2()() == window); // true

 (A)  obj.bar  (B) B this  obj.bar (A)  this  (B)  this B this  obj A this  this  undefined  () obj 

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

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

次の例では、o.f() が起動したとき、関数内の this には、o オブジェクトが関連付けられます。

js
var o = {
  prop: 37,
  f: function () {
    return this.prop;
  },
};

console.log(o.f()); // 37

o  f o.f 
js
var o = { prop: 37 };

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // 37

 o f

this  o.b  g this  o.b  o
js
o.b = { g: independent, prop: 42 };
console.log(o.b.g()); // 42

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

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

js
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

 p ff  o p.f  this  pf  p this  pJavaScript 

/ this


使 this 
js
function sum() {
  return this.a + this.b + this.c;
}

var o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  },
};

Object.defineProperty(o, "sum", {
  get: sum,
  enumerable: true,
  configurable: true,
});

console.log(o.average, o.sum); // 2, 6

コンストラクターとして

関数がコンストラクターとして (new キーワードとともに) 使用されたとき、その this は生成された新しいオブジェクトに関連付けられます。

メモ: コンストラクターの既定では、this で参照されるオブジェクトを返しますが、代わりにほかのオブジェクトを返すことができます (返値がオブジェクトではない場合、this オブジェクトが返されます)。

js
/*
 * コンストラクターは下記のように動作します。
 *
 * function MyConstructor(){
 *   // 実際の関数本体のコードはこちらになります。
 *   // プロパティに代入することで、 |this| に必要な
 *   // プロパティを作成します。例えば、
 *   this.fum = "nom";
 *   // など...
 *
 *   // 関数にオブジェクトを返す return 文があれば、
 *   // そのオブジェクトが |new| 式の結果になります。
 *   // そうでなければ、式の結果は現在 |this| に
 *   // バインドされているオブジェクトになります
 *   // (つまり、最もよく見られる一般的なケースです)。
 * }
 */

function C() {
  this.a = 37;
}

var o = new C();
console.log(o.a); // 37

function C2() {
  this.a = 37;
  return { a: 38 };
}

o = new C2();
console.log(o.a); // 38

 (C2) this ( "this.a = 37;" )

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

関数がイベントハンドラとして使用された場合、その this はリスナーが配置されている要素に設定されます (addEventListener() 以外のメソッドで動的に追加されたリスナーについては、この規約に従わないブラウザーもあります)。

js
// リスナーとして呼び出された場合は、関連づけられた要素を青にする
function bluify(e) {
  // 常に true
  console.log(this === e.currentTarget);
  // currentTarget と target が同じオブジェクトであれば true
  console.log(this === e.target);
  this.style.backgroundColor = "#A5D9F3";
}

// 文書内の各要素の一覧を取得
var elements = document.getElementsByTagName("*");

// クリックリスナーとして bluify を追加することで、
// 要素をクリックすると青くなるようになる
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener("click", bluify, false);
}

インラインイベントハンドラー内

コードがインラインの on-イベントハンドラーから呼び出されたとき、その this にはリスナーが配置されている DOM 要素が設定されます。

html
<button onclick="alert(this.tagName.toLowerCase());">Show this</button>

上記のアラートは button と表示します。ただし、外側のコードがこのように設定された this を持っているだけだということに注意してください。

html
<button onclick="alert((function() { return this; })());">
  Show inner this
</button>

この場合、内側の関数の this は設定されていないので、グローバルの window オブジェクトを返します (つまり、this が呼び出しによって設定されていないので、非 strict モードの既定オブジェクトです)。

クラス内の this


 this  this 便
js
class Car {
  constructor() {
    // 違いを示すために sayHi ではなく sayBye をバインドする
    this.sayBye = this.sayBye.bind(this);
  }
  sayHi() {
    console.log(`Hello from ${this.name}`);
  }
  sayBye() {
    console.log(`Bye from ${this.name}`);
  }
  get name() {
    return "Ferrari";
  }
}

class Bird {
  get name() {
    return "Tweety";
  }
}

const car = new Car();
const bird = new Bird();

// メソッドの 'this' の値は呼び出し元に依存します
car.sayHi(); // Hello from Ferrari
bird.sayHi = car.sayHi;
bird.sayHi(); // Hello from Tweety

// バインドされたメソッドの場合、'this' は呼び出し元に依存しません
bird.sayBye = car.sayBye;
bird.sayBye(); // Bye from Ferrari

メモ: クラスは常に strict モードのコードです。これを定義せずに this でメソッドを呼び出すとエラーが発生します。

仕様書

Specification
ECMAScript Language Specification
# sec-this-keyword

ブラウザーの互換性

BCD tables only load in the browser

関連情報