3

すぐに呼び出されるクロージャーで囲まれたJavascriptメインファイルがあります(「グローバル」を汚染しないように:

(function () {
"use strict";
   var closureVariable = [];
...
}());

コードにセミコロンではなくコンマが含まれるように、関数ヘッダーから変数を削除するときに、単純な骨の折れるコーディング エラーを作成しました。

function fred () {
    var i,

    closureVariable = [1,2,3,4];
    confused();
}
function confused () {
    console.log(closureVariable);     // Prints '[]'
}

確かに、「var i」行のセミコロンが欠けていることが問題でした。しかし、私が考えた動作は、現在ローカルで定義されている変数「closureVariable」が上位レベルのスコープ定義を隠し、ローカルで定義された変数の値がスコープチェーンの下位の関数で利用できるはずだったということです (つまり、関数「混乱」は「[1,2,3,4]」を出力する必要がありました。

ここで Javascript スコープ チェーンについて理解していないことは何ですか?

4

3 に答える 3

3
var i,

    closureVariable = [1,2,3,4];

fred関数とこのスコープで定義された関数で使用できる 2 つの新しい変数を作成します。

fredこれらの変数は、たまたま同じ名前を持っていたとしても、スコープ外で定義された変数とはまったく異なります。

ここで、シャドウイングとは、名前付き"closureVariable"の変数が、外側のスコープで同じ名前を持つ変数への直接アクセスを防ぐことを意味します。

于 2014-02-25T14:58:07.267 に答える
3

あなたが期待していることは、動的スコープとして知られています。これは有効な言語設計の選択ですが、今日では劣っていると広く考えられています。それはJavascriptが行うことではありません。多くの一般的な言語と同様に、Javascript はレキシカル スコープを使用します。つまりconfused、 のスコープは の子スコープとは見なされません。fredこれは、その定義が の定義内にないためですfredfred呼び出すという事実confusedは効果がありません。

于 2014-02-25T14:59:02.777 に答える
1

セミコロンを省略して ClosureVariable を再定義すると、 fred 関数のコンテキストでのみ再定義されました。混乱した関数はクロージャーのコンテキストに存在するため、元のクロージャー変数が引き続き表示されます。fred 関数内で定義された混乱した関数がある場合、新しい ClosureVariable が表示され、[1,2,3,4] が出力されます。

(function () {
  "use strict";
  var closureVariable = [];
  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   function confused () {
      console.log(closureVariable);     
   }

   confused();  // print [1,2,3,4]
  }
 })();

または、 fred() の外部から混乱して呼び出したい場合

(function () {
  "use strict";
  var closureVariable = [];
  var confused;

  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   confused = function () {
      console.log(closureVariable);     
   }  
  }

  confused();  // print [1,2,3,4]
 })();
于 2014-02-25T15:00:31.620 に答える