1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
|
---
title: this
slug: Web/JavaScript/Reference/Operators/this
tags:
- JavaScript
- Language feature
- Operator
- Primary Expressions
- Reference
- this
- 演算子
- 言語機能
translation_of: Web/JavaScript/Reference/Operators/this
---
<div>{{jsSidebar("Operators")}}</div>
<p><strong>関数の <code>this</code> キーワード</strong> は、JavaScript ではほかの言語と少々異なる動作をします。また、<a href="/ja/docs/Web/JavaScript/Reference/Strict_mode">厳格モード</a>と非厳格モードでも違いがあります。</p>
<p>ほとんどの場合、<code>this</code> の値はどのように関数が呼ばれたかによって決定されます(実行時結合)。これは実行時に割り当てできず、関数が呼び出されるたびに異なる可能性があります。ES5 では、関数が{{jsxref('Operators/this', "どのように呼ばれたかに関係なく <code>this</code> の値を設定する", 'The_bind_method', 1)}} {{jsxref("Function.prototype.bind()", "bind()")}} メソッドが導入され、ES2015 では、独自の <code>this</code> バインディングを行わない<a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数</a>が導入されました(これは包含するレキシカルコンテキストの <code>this</code> の値を保持します)。</p>
<div>{{EmbedInteractiveExample("pages/js/expressions-this.html")}}</div>
<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、<a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div>
<h2 id="Syntax" name="Syntax">構文</h2>
<pre class="syntaxbox notranslate">this</pre>
<h3 id="Value" name="Value">値</h3>
<p>非厳格モードでは、実行コンテキスト (グローバル、関数、eval) のプロパティで、常にオブジェクトへの参照です。厳格モードではどのような値でも取り得ます。</p>
<h2 id="解説">解説</h2>
<h3 id="Global_context" name="Global_context">グローバルコンテキスト</h3>
<p>グローバル実行コンテキスト (すべての関数の外側) では、厳格モードであるかどうかにかかわらず、<code>this</code> はグローバルオブジェクトを参照します。</p>
<pre class="brush:js notranslate">// ウェブブラウザーでは 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"
</pre>
<div class="blockIndicator note">
<p><strong>メモ:</strong> コードが実行されている現在のコンテキストに関係なく、グローバルの {{jsxref("globalThis")}} プロパティを使用していつでも簡単にグローバルオブジェクトを取得できます。</p>
</div>
<h3 id="Function_context" name="Function_context">関数コンテキスト</h3>
<p>関数内での <code>this</code> の値は、関数の呼び出され方によって異なります。</p>
<p>下記のコードは<a href="/ja/docs/Web/JavaScript/Reference/Strict_mode">厳格モード</a>ではないため、また呼び出し時に <code>this</code> の値が設定されないため、<code>this</code> は既定でグローバルオブジェクトとなり、これはブラウザーでは {{domxref("Window", "window")}} です。</p>
<pre class="brush:js notranslate">function f1() {
return this;
}
// ブラウザー上で
f1() === window; // true
// Node 上で
f1() === global; // true</pre>
<p>ただし厳格モードでは、実行コンテキストに入るときに <code>this</code> 値が設定されていないと、以下の例のように <code>undefined</code> のままになります。</p>
<pre class="brush:js notranslate">function f2() {
'use strict'; // 厳格モードにする
return this;
}
f2() === undefined; // true
</pre>
<div class="note">二番目の例において、<code>this</code> が {{jsxref("undefined")}} となるのは <code>f2</code> が直接呼び出されており、オブジェクトのメソッドやプロパティ (例えば <code>window.f2()</code>) ではないためです。この機能は初めて<a href="/ja/docs/Web/JavaScript/Reference/Strict_mode">厳格モード</a>への対応が始まったとき、一部のブラウザーが実装していませんでした。その結果、これらのブラウザーは不正確に <code>window</code> オブジェクトを返していました。</div>
<p>関数の呼び出し時に <code>this</code> の値を特定の値に設定するには、以下の例のように {{jsxref("Function.prototype.call()", "call()")}} または {{jsxref("Function.prototype.apply()", "apply()")}} を使用します。</p>
<h3 id="クラスコンテキスト">クラスコンテキスト</h3>
<p><a href="/ja/docs/Web/JavaScript/Reference/Classes">クラス</a>は関数の機能であるため、クラスと関数の <code>this</code> の動作は似ています。ただし、いくつかの違いと注意点があります。</p>
<p>クラスのコンストラクター内では、<code>this</code> は通常のオブジェクトです。クラス内のすべての非静的メソッドは <code>this</code> のプロトタイプに追加されます。</p>
<pre class="brush: js notranslate">class Example {
constructor() {
const proto = Object.getPrototypeOf(this);
console.log(Object.getOwnPropertyNames(proto));
}
first(){}
second(){}
static third(){}
}
new Example(); // ['constructor', 'first', 'second']
</pre>
<div class="blockIndicator note">
<p><strong>メモ:</strong> 静的メソッドは <code>this</code> のプロパティではありません。それらはクラス自体のプロパティです。</p>
</div>
<h3 id="派生クラス">派生クラス</h3>
<p>基本クラスのコンストラクターとは異なり、派生コンストラクターには初期の <code>this</code> バインディングがありません。{{jsxref("Operators/super", "super()")}} を呼び出すとコンストラクター内に <code>this</code> バインディングが作成され、基本的に以下のコードを評価する効果があります。ここで、Base は継承されたクラスです。</p>
<pre class="brush: js notranslate">this = new Base();</pre>
<div class="blockIndicator warning">
<p><strong>警告:</strong> super() を呼び出す前に <code>this</code> を参照するとエラーが発生します。</p>
</div>
<p>派生クラスは、<code>オブジェクト</code>を return するか、コンストラクターを持たない場合を除き、<code>super()</code> を呼び出す前に return することはできません。</p>
<pre class="brush: js notranslate">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(); // 参照エラー</pre>
<h2 id="例">例</h2>
<h3 id="関数コンテキスト内の_this">関数コンテキスト内の this</h3>
<pre class="brush:js notranslate">// オブジェクトを call や apply の最初の引数として渡すと、this がそれに結び付けられます
var obj = {a: 'Custom'};
// このプロパティはグローバルオブジェクトに設定されます
var a = 'Global';
function whatsThis() {
return this.a; // this の値は関数の呼び出し方によって変わります
function is called
}
whatsThis(); // 関数内の this として 'Global' は設定されていないので、デフォルトではグローバル/ウィンドウオブジェクトになります。
whatsThis.call(obj); // 関数内の this として 'Custom' が obj に設定されています
whatsThis.apply(obj); // 関数内の this として 'Custom' が obj に設定されています
</pre>
<h3 id="this_とオブジェクト変換">this とオブジェクト変換</h3>
<pre class="brush:js notranslate">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
</pre>
<p>なお、非厳格モードにおいて、<code>call</code> と <code>apply</code> は、<code>this</code> として渡された値がオブジェクトではない場合、内部の <code>ToObject</code> 操作を利用してオブジェクトに変換しようします。<code>7</code> や <code>'foo'</code> のようなプリミティブが渡された場合、関連するコンストラクターを使用してオブジェクトに変換されます。たとえば、プリミティブの数値である <code>7</code> は <code>new Number(7)</code> であるかのようにオブジェクトに変換され、文字列の <code>'foo'</code> は <code>new String('foo')</code> であるかのようにオブジェクトに変換されます。</p>
<pre class="brush:js notranslate">function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number]
bar.call('foo'); // [object String]
bar.call(undefined); // [object global]
</pre>
<h3 id="The_bind_method" name="The_bind_method"><code>bind</code> メソッド</h3>
<p>ECMAScript 5 で {{jsxref("Function.prototype.bind")}} が導入されました。<code>f.bind(someObject)</code> の呼び出しは、<code>f</code> と同じ内部とスコープを持つ新しい関数を生成し、ここが <code>this</code> が発生するオリジナルの関数ですが、関数がどのように使われるかにかかわらず、新しい関数では <code>bind</code> の最初の引数に永続的にバインドされます。</p>
<pre class="brush:js notranslate">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
</pre>
<h3 id="Arrow_functions" name="Arrow_functions">アロー関数</h3>
<p><a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数</a>では、<code>this</code> はそれを囲むレキシカルコンテキストの <code>this</code> の値が設定されます。グローバルコードでは、グローバルオブジェクトが設定されます。</p>
<pre class="brush: js notranslate">var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true</pre>
<div class="note">
<p>メモ: アロー関数の呼び出し時に <code>this</code> 引数が <code>call</code>, <code>bind</code>, <code>apply</code> に渡されても無視されます。呼び出しに引数を加えることはできますが、最初の引数 (<code>thisArg</code>) は <code>null</code> を設定してください</p>
</div>
<pre class="brush: js notranslate">// オブジェクトのメソッドとして呼び出す。
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</pre>
<p>何があっても、<code>foo</code> の <code>this</code> は生成されたときの値が設定されています (上記の例ではグローバルオブジェクトです)。同様のことが、ほかの関数内で生成したアロー関数にも適用されます。それらの <code>this</code> には、それを包含するレキシカルコンテキストのものになります。</p>
<pre class="brush:js notranslate">// this を返す関数を返す bar メソッドを持つ
// obj を生成します。返された関数はアロー関数
// として生成されているため、その this は
// それを包含する関数の this に永続的に拘束
// されます。bar の値は呼び出し時に設定でき、
// 返値の関数の値に順に設定します。
var obj = {
bar: function() {
var x = (() => this);
return x;
}
};
// bar を obj のメソッドとして呼び出す際、その this を obj に設定します
// 返値の関数への参照を fn に割り当てます。
var fn = obj.bar();
// 厳格モードでは、this を設定せずに fn を呼び出すと
// 通常はグローバルオブジェクトか undefined が既定値となります。
console.log(fn() === obj); // true
// しかし obj のメソッドを call することなく参照するのは要注意です。
var fn2 = obj.bar;
// するとアロー関数の呼び出しで this は bar の
// this に従うため window と同じになります。
console.log(fn2()() == window); // true
</pre>
<p>上記では、関数 (この無名関数を A と呼びます) に <code>obj.bar</code> が返すアロー関数として生成されたほかの関数 (この無名関数を B と呼びます) を割り当てています。結果として、呼び出されたときに関数 B の <code>this</code> は、永続的に <code>obj.bar</code> (関数 A) の <code>this</code> が設定されます。返された関数 (関数 B) が呼びされるとき、その <code>this</code> は常に最初に設定されたものになります。上記のコード例では、関数 B の <code>this</code> は <code>obj</code> である関数 A の <code>this</code> が設定されているため、通常はその <code>this</code> に <code>undefined</code> かグローバルオブジェクト (または、以前の例のグローバルコンテキストのように、いずれかのメソッド) が設定されますが、<code>obj</code> の設定が残ります。</p>
<h3 id="As_an_object_method" name="As_an_object_method">オブジェクトのメソッドとして</h3>
<p>関数がオブジェクトのメソッドとして呼び出されるとき、その <code>this</code> にはメソッドが呼び出されたオブジェクトが設定されます。</p>
<p>次の例では、<code>o.f()</code> が起動したとき、関数内の <code>this</code> には、<code>o</code> オブジェクトが関連付けられます。</p>
<pre class="brush:js notranslate">var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); // 37
</pre>
<p>この振る舞いは、関数定義の方法や場所に全く影響を受けないことに注意してください。前述の例では、<code>o</code> の定義中に <code>f</code> メンバーとして関数をインラインに定義しています。しかし、関数を最初に定義して、後から <code>o.f</code> に付け足すことができます。その結果は同じ振る舞いになります。</p>
<pre class="brush:js notranslate">var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // 37
</pre>
<p>これは、関数が <code>o</code> の <code>f</code> のメンバーとして呼び出されることだけが重要なことを示しています。</p>
<p>同様に、<code>this</code> の関連付けは、最も直近のメンバー参照にのみ影響を受けます。次の例では、関数が呼び出すとき、オブジェクト <code>o.b</code> の <code>g</code> メソッドとして呼び出しています。実行時に、関数内の <code>this</code> は <code>o.b</code> を参照します。オブジェクト自体が <code>o</code> のメンバーであるという事実は何の意味もありません。最も直近の参照のみが重要なのです。</p>
<pre class="brush:js notranslate">o.b = {g: independent, prop: 42};
console.log(o.b.g()); // 42
</pre>
<h4 id="this_on_the_objects_prototype_chain" name="this_on_the_objects_prototype_chain">オブジェクトのプロトタイプチェーン上の <code>this</code></h4>
<p>同じ概念が、オブジェクトのプロトタイプチェーンのどこかに定義されたメソッドにも当てはまります。メソッドがオブジェクトのプロトタイプチェーン上にあった場合、メソッドがオブジェクト上にあるかのように、<code>this</code> はメソッドを呼び出したオブジェクトを参照します。</p>
<pre class="brush:js notranslate">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
</pre>
<p>この例では、変数 <code>p</code> に割り当てられたオブジェクト自身は <code>f</code> プロパティを持たず、プロトタイプから継承しています。しかし、<code>f</code> に対する検索が、最終的に <code>o</code> でその名前を持つメンバーを見つけることは重要ではありません。検索は <code>p.f</code> への参照から開始されるため、関数内の <code>this</code> は <code>p</code> として参照されるオブジェクトの値を取ります。<code>f</code> は <code>p</code> のメソッドとして呼ばれたため、その <code>this</code> は <code>p</code> を参照します。これは、JavaScript のプロトタイプ継承の興味深い機能です。</p>
<h4 id="this_with_a_getter_or_setter" name="this_with_a_getter_or_setter">ゲッター/セッターと <code>this</code></h4>
<p>再度、同じ概念が、ゲッターやセッターから呼ばれる関数にも当てはまります。ゲッターやセッターとして使用される関数は、このプロパティを設定するか、または得られている元のオブジェクトに関連付けられている <code>this</code> を持ちます。</p>
<pre class="brush:js notranslate">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
</pre>
<h3 id="As_a_constructor" name="As_a_constructor">コンストラクターとして</h3>
<p>関数がコンストラクターとして ({{jsxref("Operators/new", "new")}} キーワードとともに) 使用されたとき、その <code>this</code> は生成された新しいオブジェクトに関連付けられます。</p>
<div class="note">
<p>コンストラクターの既定では、<code>this</code> で参照されるオブジェクトを返しますが、代わりにほかのオブジェクトを返すことができます (返値がオブジェクトではない場合、<code>this</code> オブジェクトが返されます)。</p>
</div>
<pre class="brush:js notranslate">/*
* Constructors work like this:
*
* function MyConstructor(){
* // Actual function body code goes here.
* // Create properties on |this| as
* // desired by assigning to them. E.g.,
* this.fum = "nom";
* // et cetera...
*
* // If the function has a return statement that
* // returns an object, that object will be the
* // result of the |new| expression. Otherwise,
* // the result of the expression is the object
* // currently bound to |this|
* // (i.e., the common case most usually seen).
* }
*/
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
</pre>
<p>最後の例 (<code>C2</code>) では、構築中にオブジェクトを返しているので、<code>this</code> が結び付けられている新しいオブジェクトは単に破棄されています。(これは根本的に "<code>this.a = 37;</code>" ステートメントを死んだコードにしてしまっています。これは実行されるので、正確には死んだコードではありませんが、外部への影響がありません。)</p>
<h3 id="As_a_DOM_event_handler" name="As_a_DOM_event_handler">DOM イベントハンドラーとして</h3>
<p>関数がイベントハンドラとして使用された場合、その <code>this</code> はリスナーが配置されている要素に設定されます ({{domxref("EventTarget/addEventListener", "addEventListener()")}} 以外のメソッドで動的に追加されたリスナーについては、この規約に従わないブラウザー-もあります)。</p>
<pre class="brush:js notranslate">// リスナーとして呼び出された場合は、関連づけられた要素を青にする
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);
}</pre>
<h3 id="In_an_inline_event_handler" name="In_an_inline_event_handler">インラインイベントハンドラー内</h3>
<p>コードがインラインの <a href="/ja/docs/orphaned/Web/Guide/Events/Event_handlers">on-イベントハンドラー</a>から呼び出されたとき、その <code>this</code> にはリスナーが配置されている DOM 要素が設定されます。</p>
<pre class="brush:js notranslate"><button onclick="alert(this.tagName.toLowerCase());">
Show this
</button>
</pre>
<p>上記のアラートは <code>button</code> と表示します。ただし、外側のコードがこのように設定された <code>this</code> を持っているだけだということに注意してください。</p>
<pre class="brush:js notranslate"><button onclick="alert((function() { return this; })());">
Show inner this
</button>
</pre>
<p>この場合、内側の関数の <code>this</code> は設定されていないので、グローバルの window オブジェクトを返します (つまり、<code>this</code> が呼び出しによって設定されていないので、非厳格モードの既定オブジェクトです)。</p>
<h3 id="クラスの中の_this">クラスの中の this</h3>
<div class="blockIndicator note"></div>
<p>通常の関数と同様に、メソッド内の <code>this</code> の値は、どのように呼び出されるかによって異なります。クラス内の <code>this</code> が常にクラスのインスタンスを参照するように、この動作をオーバーライドしておくと便利な場合もあります。これを実現するには、コンストラクターでクラスのメソッドをバインドします。</p>
<pre class="brush: js notranslate">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</pre>
<div class="blockIndicator note">
<p><strong>メモ:</strong> クラスは常に厳格モードのコードです。これを定義せずに <code>this</code> でメソッドを呼び出すとエラーが発生します。</p>
</div>
<h2 id="Specifications" name="Specifications">仕様</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">仕様書</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-this-keyword', 'The this keyword')}}</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2>
<p>{{Compat("javascript.operators.this")}}</p>
<h2 id="See_also" name="See_also">関連情報</h2>
<ul>
<li><a href="/ja/docs/Web/JavaScript/Reference/Strict_mode">厳格モード</a></li>
<li><a href="https://dmitripavlutin.com/gentle-explanation-of-this-in-javascript/">Gentle explanation of 'this' keyword in JavaScript</a></li>
<li>Getting the global context: {{jsxref("globalThis")}}</li>
</ul>
|