はじめに
thisについても当たり前のことが多いですが、自分用のためにもおさらいメモです
入れ子関数内のthisとか知らないときは本当に悩むものですよね
ながれ
こんな感じの流れでおさらいをまとめます
1.thisが参照するもの
2.thisの決定
3.入れ子関数内のthis
4.thisの束縛
5.コンストラクタ関数内のthis
6.prototypeメソッド内のthis
1.thisが参照するもの
・ブラウザなどのグローバルスコープではwindowオブジェクト
・関数の中ではその関数が格納されているオブジェクト
※new、call、applyを使う場合を除く
コードで確認
※ グローバルスコープの場合 console.log(this); // 出力 : window ※ 関数の中の場合 var hoge = { say: function(){console.log(this);} }; hoge.say(); // 出力 : Object {say: function}
2.thisの決定
thisの参照は関数が呼ばれたコンテキストによって変わる
コードで確認
var hoge = 'mone'; var hogeObject = { hoge: 'hogeObject property'}; var whatIsHoge = function(){ console.log(this.hoge); } /* whatIsHoge関数をhogeObjectのwhatIsHogeメソッドにポイントする */ hogeObject.whatIsHoge = whatIsHoge; hogeObject.whatIsHoge(); // 出力 : hogeObject property whatIsHoge(); // 出力 : mone
3.入れ子関数内のthis
入れ子関数内でthisが呼ばれた場合は、thisはグローバルオブジェクト(ブラウザならwindow)を参照
※ ECMAScript5ではこの仕様は改修予定らしい
コードで確認
/* 単純な入れ子の場合 */ var piyo = { func1: function(){ console.log(this); // 出力 : Object {func1: function} var func2 = function(){ console.log(this); }(); // 出力 : Window } } piyo.func1(); /* オブジェクトのメソッドに引数で渡した場合 */ var pico = { func1: function(func){ console.log(this); // 出力 : Object {func1: function} func(); // 出力 : Window } } pico.func1( function(){ console.log(this);} );
4.thisの束縛
入れ子内の関数であっても、
スコープチェーンやcall(またはapply)を使うことでthisのコンテキストをコントロールできる
ということで、「3.入れ子関数内のthis」の例を
・スコープチェーンを使って束縛
・call、applyを使って束縛
という形でthisがpiyoオブジェクトをポイントするように変えてみます
スコープチェーンを使って束縛
var piyo = { func1: function(){ /* func1のスコープにある_thisにthisへの参照を保持させる */ var _this = this; console.log(this); // 出力 : Object {func1: function} var func2 = function(){ console.log(this); // 出力 : Window console.log(_this); // 出力 : Object {func1: function} }(); } } piyo.func1();
call、applyを使って束縛
var piyo = { func1: function(){ var _this = this; console.log(this); // 出力 : Object {func1: function} var func2 = function(){ console.log(this); // 出力 : Object {func1: function} console.log(_this); // 出力 : Object {func1: function} }.call(this); // applyでもOK } } piyo.func1();
call、applyの使い方
↑は「3.入れ子関数内のthis」の例を元に無理矢理callを使った感があるので
call、applyのおさらい的な感じで使い方もメモ
var hoge = {}; var testFunc = function(arg1, arg2){ this.prop1 = arg1; this.prop2 = arg2; console.log(this); } testFunc(); // 出力 : Window testFunc.call(hoge, 'aaa', 'bbb'); // 出力 : Object {prop1: "aaa", prop2: "bbb"} testFunc.apply(hoge, ['aaa', 'bbb']); // 出力 : Object {prop1: "aaa", prop2: "bbb"}
5.コンストラクタ関数内でのthis
new演算子でコンストラクタ呼び出しをする場合はthisはインスタンスを参照する
コードで確認
var Animal = function(kind) { console.log(this); this.kind = kind; /* 入れ子関数っぽいけど...? */ this.sayKind = function(){console.log(this.kind);} } /* newをつけてコンストラクタ呼び出し */ var dog = new Animal('dog'); // 出力 : Animal {} console.log(dog.kind); // 出力 : dog dog.sayKind(); // 出力 : dog /* newをつけずに関数呼び出し */ var dame_dog = Animal(); // 出力 : Window console.log(dame_dog.kind); // Uncaught TypeError dame_dog.sayKind(); // Uncaught TypeError
6.prototypeメソッド内のthis
prototypeメソッド内のthisはメソッドが呼ばれたインスタンスを参照する
コードで確認する
var Animal = function(kind){ this.kind = kind; }; Animal.prototype.sayKind = function(){console.log(this.kind);} var dog = new Animal('dog'); var cat = new Animal('cat'); dog.sayKind(); // 出力 : dog cat.sayKind(); // 出力 : cat
開眼!JavaScriptという書籍を読んでいたらよくまとまっていたのでそれをだいぶ参考にして書いてみました
これでthisについては安心ですね!
この記事で参考にした書籍
オライリージャパン
売り上げランキング: 11,609