2011-07-02 11 views
5

このコードは、"!"がコンソールに記録されるようにします。JavaScriptと匿名関数のクロージャの詳細

var g = {}; 
(function() { 
    var t = this; 
    t.x = "x"; 
    g.a = function() { 
     console.log(t.x); 
    }; 
})(); 

(function() { 
    var t = this; 
    t.x = "!"; 
    g.b = function() { 
     console.log(t.x); 
    }; 
})(); 

g.a(); 

匿名機能は、thisを共有しますか? thisが間違っていますか?私はここで何が起こっているのか分かりません。

g.a()は、最初の匿名関数で定義されたxの値を返すことを続けたいと思います。

違いがある場合はnode.jsを使用しています。

答えて

4

は、global object[docs]を指します。したがって、この場合両方の関数でthisが実際に同じ要素を参照し、2番目の呼び出しでxを上書きしています。

thisがどのオブジェクトを参照しているかは、関数の呼び出し方法によって決まります。

  • あなただけfuncName();で関数を実行する場合は、thisグローバルオブジェクトを指します。
  • 関数がオブジェクトのプロパティに割り当てられている場合は、obj.funcName()thisがオブジェクトを参照します。
  • new演算子を使用して関数を呼び出すと、new funcName();thisは関数プロトタイプから継承した空のオブジェクトを参照します。

また、明示的にcall[docs]apply[docs]を使用してthisを設定することができます。


代わりthisを参照して、あなたは両方の機能に新しいオブジェクトを作成することができます。

var t = {}; 

追加注:それはあなたがブラウザでコードを実行するかどうか違いはありませんかnode.jsでグローバルオブジェクトは仕様の一部であり、実行環境によって提供される必要があります。ブラウザではwindowオブジェクトですが、node.jsにはありませんが、仕様に従う限り問題はありません。

+0

'this'は関数を参照していませんか? –

+3

@luxun:あなたはその機能自体を意味していますか?いいえ、決して。 –

+3

あなたが特別なことをするように特別に設定しない限り、決してそうはなりませんが、それはちょっと変わったものです。確かに、デフォルトや何かではありません。 – Pointy

3

フェリックス・クリングは正しい長い答えです。しかし、私はあなたが実際にしたいと思うものとチャイムしたい:

var g = {}; 
(function() { 
    var x = "x"; 
    g.a = function() { 
     console.log(x); 
    }; 
})(); 

(function() { 
    var x = "!"; 
    g.b = function() { 
     console.log(x); 
    }; 
})(); 

g.a(); // "x" 
g.b(); // "!" 

g.a()g.b()は両方xをプリントアウトしますが、各機能は、クロージャと共有自分の別のxを持っています。これらのvarsをプライベートにする必要がある場合は、これらの各関数の内部でのみアクセスできます。これを非表示にして、複数の呼び出しでそれらを保持する方法です。

1

これまで説明したように、Chromeのデバッガでこのスクリプトを見ると、両方の匿名関数の「this」値がグローバル変数「ウィンドウ」に設定されています。これは、各無名関数がwindow.xの値を設定し、最後に実行されたものが勝ち残り値になることを意味します。したがって、2番目の無名関数が実行された後にwindow.x == "!"が実行されます。

「これ」が何であるか、実際にこのコードで達成しようとしていることがわかりませんので、私はどのような選択肢を提案するか分かりません。無名関数の前の状態を内部関数に残すだけなら、ローカル変数(クロージャでは生き残る)に頼ることができ、 "this"参照を全く使わないことができます。 Squeegyの例はそれを示しています。

関連する問題