Skip to content

Latest commit

 

History

History
93 lines (56 loc) · 4.01 KB

File metadata and controls

93 lines (56 loc) · 4.01 KB

thisはどのように動作するのか

JavaScriptのthisと名付けられた特殊なキーワードは他のプログラム言語と違うコンセプトを持っています。JavaScriptのthisは正確に5個の別々の使い道が存在しています。

グローバルスコープとして

this;

thisをグローバルスコープ内で使用すると、単純にグローバルオブジェクトを参照するようになります。

関数呼び出しとして

foo();

このthisは、再度グローバルオブジェクトを参照しています。

ES5での注意: strictモードでは、このグローバルのケースはもはや存在していません。 この場合thisundefined値を代わりに持つことになります。

メソッド呼び出しとして

test.foo(); 

この例ではthistestを参照します。

コンストラクター呼び出し

new foo(); 

newキーワードが付いた関数呼び出しはコンストラクターとして機能します。関数内部ではthis新規に作成されたObjectを参照します。

thisの明示的な設定

function foo(a, b, c) {}

var bar = {};
foo.apply(bar, [1, 2, 3]); // 配列は下記で展開される
foo.call(bar, 1, 2, 3); // 結果はa = 1, b = 2, c = 3

Function.prototypecallapplyメソッドを使用した時には、呼び出された関数の内部でのthisの値は、対応する関数呼び出しの最初の引数に明示的に設定されます。

結果として、上記の例ではメソッドケースが適用されずfooの内部のthisbarに設定されます。

注意: thisObjectリテラル内部のオブジェクトを参照しません。 ですので、var obj = {me: this}でのmeobjを参照しませんthisはここで紹介ている5個のケースの内どれか一つに束縛されます。

良くある落し穴

これらのケースのほとんどは理にかなったものですが、最初のケースは実際に利用されることが絶対にないので、間違った言語設計だとみなせるでしょう。

Foo.method = function() {
    function test() {
        // このファンクションはグローバルオブジェクトに設定される
    }
    test();
}

良くある誤解としてtestの中のthisFooを参照しているというものがありますが、そのような事実は一切ありません。

testの中のFooにアクセスする為には、Fooを参照するmethodのローカル変数を作る必要があります。

Foo.method = function() {
    var that = this;
    function test() {
        // ここでthisの代わりに使用する
    }
    test();
}

thatは通常の変数名ですが、外部のthisの参照の為に良く使われます。クロージャと組み合わせる事でthisの値を渡す事ができるようになります。

メソッドの割り当て

JavaScriptを使用する上で、もう一つ動かないものが関数のエイリアスです。これは変数へメソッドを割り当てする事です。

var test = someObject.methodTest;
test();

最初のケースのtestは通常の関数呼び出しになる為に、この中のthisは、もはやsomeobjectを参照できなくなってしまいます。

thisの遅延バインディングは最初見た時にはダメなアイデアに見えますが、プロトタイプ継承により、きちんと動作します。

function Foo() {}
Foo.prototype.method = function() {};

function Bar() {}
Bar.prototype = Foo.prototype;

new Bar().method();

methodBarのインスタンスにより呼び出された時に、thisはまさにそのインスタンスを参照するようになります。