thisの挙動

2013/08/28 22:04

javascriptのthisの挙動は難しいと言われています。
なぜ難しいかというと同じ書き方のロジックでも使われる状況によって挙動が変わってくるからです。
thisの挙動は4つのパターンがあります。 4つのパターンについてサンプルを交えて説明を書きたいと思います。

1.メソッド呼び出し

var Memo = {
  title: "thisの挙動",
  output: function () {
    console.log(this.titile + "を確認する。");
  }
}
Memo.output(); // => thisの挙動を確認する。

メソッド呼び出し(Memo.output)内で呼び出す場合は同一のクラスを参照します。
クラスメソッドからクラス変数を参照するのと同じイメージになると思います。

2.グローバル関数呼び出し

title = "thisの挙動";
function output() {
  var title = "うその挙動";
  console.log(this.title + "を確認する。");
}
output(); // => thisの挙動を確認する。

グローバル関数を作成しそのまま使用した場合、thisの参照先はグローバル(windowまたはglobal)になります。
なのでtitleの宣言の仕方を下記の書き方でも動きは同じになります。

global.title = "thisの挙動"; // node.js
window.title = "thisの挙動"; // ブラウザ

3.コンストラクタ呼び出し

title = "うその挙動";
function Memo () {
  this.title = "thisの挙動";
}
Memo.prototype.output = function () {
  console.log(this.title + "を確認する。");
}
var memo = new Memo();
memo.output(); // => thisの挙動を確認する。

Memo関数を作ったところだけを見ると一見グローバル変数を参照しているように見えます。
だけどnewでインスタンスしたとたんにthisの参照先が変わってしまいます。
この辺になると挙動が難しくなってくると思いますがjavascriptのデザインパターンを考えると必要な知識なので押さえておく必要があります。

4.apply呼び出し

title = "thisの挙動";
function Memo () {
  this.title = "うその挙動";
}
Memo.prototype.output = function (string) {
  console.log(this.title + string);
}
var memo = new Memo();
memo.output.apply(global, ["を確認する。"]); // => thisの挙動を確認する。

コンストラクタ呼び出しだと通常はtitleに”うその挙動”が返ってきそうですが。
output関数にapplyを指定し第1引数を指定すると呼び出し先でthisに置き換わります。
第2引数には関数に渡す引数を配列で渡します。

総括

最近のWeb開発ではサーバの処理からクライアントの処理に比重があがってきてます。
比重が上がる中でjavascriptの可読性をあげるためにデザイン化は必ず必要になってきます。
デザイン化を行うためにはthisの存在はかかせなくなってくるため挙動についてはきちんと理解しておきましょう。