3

JavaScript クロージャがどのように機能するかを正確に理解するのに苦労しています。これら 2 つの関数を見て、複数回呼び出すとまったく異なる結果が生成されるという違いを教えてください。

機能 1

var add = (function() {
  var counter = 0;
  return function() {
    return counter += 1;
  }
})();
console.log(add()); // result is 1
console.log(add()); // result is 2
console.log(add()); // result is 3

機能 2

function add() {
  var counter = 0;
  function() {
    return counter += 1;
  }
  plus();
}
console.log(add()); // result is 1
console.log(add()); // result is 1
console.log(add()); // result is 1

4

6 に答える 6

3

最初の例では、counter が宣言されており、呼び出し時に呼び出される関数addは基本的に次のとおりです。

function (){
    return counter += 1;
}

が呼び出されるcounterたびに が再宣言されるわけではないため、これは重要です。add

2 番目の例では、が呼び出されるcounterたびに再宣言されています。add

于 2016-06-29T06:35:34.367 に答える
2

この JavaScript 関数のペアはどのように違うのでしょうか?

各例では、2 つの関数を宣言しており、一方が他方の内部にネストされています。

最初の例では、外側の関数を 1 回呼び出し、内側の関数を返し、それを に代入していaddます。つまり、呼び出しは内部関数addのみを実行します。

2 番目の例でaddは、外部関数を参照します。したがって、呼び出しaddは常に外部関数と内部関数を実行します。


最初の例を少し書き直すと、違いがよくわかるかもしれません (それでも同じ結果が得られます)。

// Example 1
function add() {
  var counter = 0;
  return function plus() {
    return counter += 1;
  }
}

var plus = add();
console.log(plus());
console.log(plus());

addが一度しか呼び出されないことに注意してください。これは、var counter = 0;が一度だけ実行されることを意味し、plus実際に呼び出している関数です。plus内で定義されているためadd、 にアクセスできますcounter

于 2016-06-29T06:40:43.907 に答える
2

ケース 1 では、外側のIIFEにClosureを持つ関数を返しています。その結果、返された関数は、返された後でも count の値を格納できるため (つまり、クロージャー)、呼び出すたびに更新された値を取得します。add()

あなたのケース2は間違っているようです。plus関数が定義されていません。そして、あなたがそれを定義したとしても、あなたundefinedは何も返していないので、あなたは得るでしょうadd()

function add() {
  var counter = 0;
  function plus () {
    return counter += 1;
  }
  plus();
}
console.log(add()); // result is 1
console.log(add()); // result is 1
console.log(add()); // result is 1

あなたがそれから戻ったとき、あなたは実際にあなたが呼び出すたびに毎回実行の結果を返しているので、あなたはplus()だけを得るでしょう1counter += 1counter is reset to 0add()

于 2016-06-29T06:35:06.823 に答える
1

エンクロージャーの外部にあるエンクロージャー内で定義された変数にアクセスすることはできません。これは、同じ変数名が複数の関数で使用されている場合など、競合を回避するのに役立ちます。

于 2016-06-29T06:31:35.650 に答える
0

最初の例では、外側の関数が 1 回実行され、カウンター変数がゼロに設定されます。外側の関数は内側の関数を返し、変数に代入しますadd。を呼び出すadd()と、内部関数は宣言されたコンテキストで実行されるため、カウンター変数をインクリメントできます。

2 番目の例では、外側の関数が という名前で宣言されていますadd。を呼び出すたびに、この外部関数を実行しますadd。この外側の関数は毎回カウンターをゼロに設定し、内側のplus関数を実行してカウンターを 1 にインクリメントし、それを返します。

于 2016-06-29T06:41:08.167 に答える
0

最初のスニペットで正確に何が起こるかを次に示します。

var add = (function() {
  var counter = 0;
  return function() {
    return counter += 1;
  }
})();

上記のステートメントでは、変数addに を増加させる関数を割り当てていますcounter

注意事項:

  1. この関数は、エンクロージャ関数を実行することで取得できます。(同封関数が返すものに注意してください)

  2. ()その直後に配置することで、エンクロージャー機能を実行します。

これで、変数addは を増やすだけの関数になりましたcounter。ここでは、クロージャを作成するように環境が設定されているため、内部関数は常にcounter.

addしたがって、変数を介して内部関数を実行するたびに、増加した数が表示されます。

于 2016-06-29T06:46:35.440 に答える