setTimeout関数でthisを使うには

今日ちょこっと引っかかったのでメモ。

次のようなコードを書いた時、setTimeout関数内からthis.nameを参照できなかった。

var Person = function(name) {
  this.name = name;
};

Person.prototype.sayHello = function() {
  // これはOK
  alert("Hello, my name is " + this.name);

  // これはNG
  setTimeout(function() {
    alert("My name is " + this.name);
  }, 1000);
};

onload = function() {
  var hiroshi = new Person("Hiroshi Sato");
  hiroshi.sayHello();
};


調べてみたら、setTimeoutで呼ばれる関数の実行コンテキストが変わってしまうらしい。
(thisにはグローバルオブジェクトがセットされる)
window.setTimeout - Web API インターフェイス | MDN


なので、クロージャを使えばオーケー。

var Person = function(name) {
  this.name = name;
};

Person.prototype.sayHello = function() {
  // ここがポイント!
  var that = this;
  setTimeout(function() {
    alert("My name is " + that.name);
  }, 1000);
};

onload = function() {
  var hiroshi = new Person("Hiroshi Sato");
  hiroshi.sayHello();
};

解決できて良かった!!