6

ここで何かをまっすぐにしたいので...2つの質問があります

以下の関数はクロージャを作成します。

function Foo(message){
    var msg = message;

    return function Bar(){ 
        this.talk = function(){alert(msg); }
    }
};

Q:クロージャーとはどの機能FooですかBar一度閉まると返ってくるので、
いつも閉店だと思っていました。FooBarBar

次...

以下は無名関数の定義です。

()();

Q:この無名関数内の内部関数もクロージャですか?

(function(){ /* <-- Is this function also a closure? */ })();
4

2 に答える 2

4

ここでは第一原理を使用する必要があります。Javascriptは字句スコープを使用します。これは、実行コンテキストのスコープがコードの定義方法(字句)によって決定されることを意味します。

関数の定義は、関数内で「閉じられている」 ため、クロージャが作成されるBar原因あると言えます。msg

クロージャーの実際の作成は実行時に行われます(これはmsg、実行されるまでコンピュータープログラムでは何も起こらないため、トートロジーステートメントのようなものです)。実行時の変数の値などをチェーンの上位で確認します。BarBarFoo

私はあなたの質問に2つの答えを与えます。衒学的な答えは次のとおりです。どちらの機能自体もクロージャーではありません。これは、関数内の変数の定義であり、実行時の関数の実行コンテキストと組み合わされて、クロージャーを定義します。一般的な答えは次のとおりです。変数を閉じる関数はすべてクロージャです(あなたの場合はバー)。

Javascriptを使用するときに誰もが遭遇する問題を考えてみてください。

function A(x) {
   var y = x, fs = [];

   for (var i = 0; i < 3; i++) {
       fs.push(function(){
         console.log (i + " " + x);
       })
   }

   fs.forEach(function(g){g()})  
}

A('hi')

ほとんどの人は、これにより「hi 1」、「hi 2」、「hi3」の出力が生成されると言うでしょう。ただし、「hi3」を3回生成します。配列に追加される関数の定義だけで、外部関数で定義された変数を使用してクロージャーを作成した場合、これはどのようになりますか?

これは、クロージャを定義するために実行コンテキストが必要なためです。これは、実行時まで発生しません。配列内の関数の実行時にi、値は。になります3。ステートメントではforEach、これが実行コンテキストであるため、出力では常に3が使用されます。

于 2012-08-20T14:30:56.880 に答える
1

Bar閉鎖です。

それはその環境の変数をBar 閉じると言います。msg

ほとんどの場合、クロージャという言葉は次のことを意味します。囲み関数で囲みスコープで定義された少なくとも1つの変数を使用する関数。

2番目の質問に答えるには:2(function(){ ... })()つではなく1つの匿名関数がどのように見えるかです。別の関数内にネストされていない限り、通常はクロージャとは呼ばれません。ただし、その無名関数内にネストされた関数はクロージャになる可能性があります(多くの場合、クロージャになります)。

于 2012-08-20T14:49:53.113 に答える