JavaScriptにおけるthisの違い
- 2015/02/20
- てっちゃん
こんにちは、デザイナーのてっちゃんです。先日健康診断の結果が返ってきて判定は「A」でした。
1年間取り組んできた事がしっかりと反映されてて嬉しかったです。
お祝いにステーキ食べましたが体重はキープ出来ました!素晴らしい!!
さて、今回はJavaScriptにおけるthisの違いを書いていこうと思います。
最近javascriptについて勉強しているところで、下記を題材にしています。
- プロトタイプチェーン
- スコープ
- クロージャ
まずはプロトタイプチェーンからと思いましたが、これを理解するのにさらに以下を知らないとわからなかったです。
プロトタイプ→コンストラクタ(クラス)→thisの種類。←イマココ
というわけでthisの違いについて書いていこうと思います。
thisには4種類(細かく分けるともっとあるのですが、大まかには4つで!)あり、以下のようになっています。
- メソッドからの参照
- 関数からの参照
- コンストラクタからの参照
- apply,callメソッド
1.メソッドからの参照
1 2 3 4 5 6 7 |
var myObeject1 = { value: 'myObeject1', fn: function() { console.log(this.value); } } myObeject1.fn(); |
myObeject1内で定義た関数fnをmyObeject1から呼び出しをしている。
この場合は、単純にmyObeject1を見ています。
こんなのはいかがでしょうか?
1 2 3 4 5 6 7 8 9 10 11 12 |
var myObeject1 = { value: 'myObeject1', fn: function() {//*A console.log(this.value); } } var myObeject2 = { value: 'myObeject2', fn: myObeject1.fn//*B } } myObeject2.fn(); |
この実行結果は「myObeject2」となります。*Aの関数オブジェクトはmyObeject1に所属しているわけではなく、独立したオブジェクトとして存在していて、呼び出された元によってかわります。 よって、定義された関数オブジェクトとは関係なし呼び出された関数を見ています。
2.関数からの参照
1 2 3 4 5 6 7 |
var value = 'global'; function show() { console.log(this.value); var value = 'local'; } show(); |
このthisはグローバルオブジェクト(window)を参照しているので「global」になります。こちらをみるとよくわかると思います。
1 2 3 4 5 6 |
var value = 'global'; function show() { console.log(value); var value = 'local'; } show(); |
こちらは、thisがついていないので関数内で名前解決しようとするため「undefined」になります。さらに、var value = 'local';がなければグローバルオブジェクト(window)を参照しに行くので「global」となります。
3.コンストラクタ呼び出し
1 2 3 4 5 6 7 8 9 10 11 |
function MyObject(value) { this.value = value; this.increment = function() { this.value++; }; } var myObject = new MyObject(0); console.log(myObject.value); // 0 myObject.increment(); console.log(myObject.value); // 1 |
「new」をつけてインスンタンスを生成しています。
その生成されたインスタンス自身を参照するのがここでの「this」になります。
4.apply,call呼び出し
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var myObject = { value: 1, show: function() { console.log(this.value); } }; var yourObject = { value: 3 }; myObject.show(); // 1 myObject.show.apply(yourObject); // 3 myObject.show.call(yourObject); // 3 |
apply」と「call」を使うと「強制的にthisを束縛」できます。この2つの違いはメソッドを呼び出した時の引数を配列で取るかどうかです。
まとめ
メソッド内での this は、呼び出されたメソッドのオブジェクトのプロパティとして呼び出されたかによって、this が何を指すのかが変わります。