旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

thisを整理する

2007年5月9日

javascriptのthisのことです。
よくわからないで使ってたなということで、まとめようと。

なお、サンプルコードのconsole.logはFireBug専用関数です。
実行環境により適宜変えてくださいませ。

– thisは、thisを記述した関数オブジェクトを格納しているオブジェクトへの参照である。

var foo = function(){
console.log(this);
};
var obj = {};
foo.call(window); // windowを出力
foo.call(obj); // objを出力
– thisへの値を代入や宣言をし直すことは出来ない

var this;
this = null;

はエラー。

– thisは、ダイナミックスコープの変数である
例1

var make = function(){
return function(){
console.log(this);
};
};
var maked = make();
maked.call(window); // windowオブジェクトを出力
maked.call(foo);    // fooオブジェクトを出力
var maked2 = make.call(foo);
maked2.call(window); // windowオブジェクトを出力
maked2.call(foo);    // fooオブジェクトを出力

例2

var make = function(){
var self = this;
return function(){
console.log(self);
};
};
var maked = make();
maked.call(window); // windowオブジェクトを出力
maked.call(foo);    // windowオブジェクトを出力
var maked2 = make.call(foo);
maked2.call(window); // fooオブジェクトを出力
maked2.call(foo);    // fooオブジェクトを出力

例1のmake関数内のthisは
レキシカルスコープ的に考えるとmake関数実行時のthisが格納されるので
それを受けてreturnされるmaked・maked2関数のthisも、
make関数を呼び出したオブジェクトを参照するはずです。

しかし、thisはダイナミックスコープなので、
「自分が所属しているオブジェクトがthisになる」というルールに基づいて、
実行時の環境にのみ影響を受け、maked.callの第一引数がその所属オブジェクトになります。
また、make関数実行時の環境であるthisはどこからも参照されないため、
メモリから消去されます。

一方、例2のmake関数内のselfは
returnしたmaked・maked2関数から参照され、
selfから参照されているmake関数内のthisもメモリ上に残り、
つまりは、make関数実行時の環境が残り、make・maked関数はクロージャとなります。

ということで
ほとんど人から聞いた話やら、検証結果やら、推測やらで成り立っているので
間違ってたら厳しい口調で突っ込んでくれるといいなと思ってます。

***追記***
ダイナミックスコープについての例文追加

例3

var foo = function(){
console.log(this); // hogeオブジェクトを出力
(function(){console.log(this);})(); // windowオブジェクトを出力
};
var hoge = {};
foo.call(hoge);

無名関数はwindow所属になる(常にかどうかは不明です)

例4

var list = [1];
var foo = function(){
console.log(this); // hogeオブジェクトを出力
list.each(function(){
console.log(this); // windowオブジェクトを出力
});
};
var hoge = {};
foo.call(hoge);

渡した無名関数でも同じ、蛇足っすね。