3

開始値、ステップ値、終了値に基づいて整数の配列を作成する Range という単純な関数があります...

function Range (start, end, step) {

  // default step is 1..
  if (step === undefined ) step = 1;

  // creating an array...
  var arr = [], index = 0;

  while(start <= end) {
  arr[index]  = start ;
  index += 1;
  start += step; 
  }

  // simple function expressions
  var getAll = function () {
    return arr  ;  
  };

  var getOne = function(n) {
    return arr[n] ;
  };


  // returns a unnamed function ..
  return function(i) { 
    if (i === undefined) { return getAll() ;}
    else {return getOne(i); } 
  };  // not an iife

} 

したがって、基本的にRangeは名前のない関数を返す関数であり、関数Rangeで宣言された名前付き関数式を再び返します..エラー..わかりません..そのようなもの...

今、以下のコード...

var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
var first10Odd = Range(1,20,2) ; // and Range is called again..

alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... } 

alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19

alert(first10(0)); // alerts - 1 
alert(first10Odd(9)); // alerts- 19

コメントで指定されているようにアラートがアラートを出すのはなぜですか?? ... Rangeは単なる関数であり、オブジェクトコンストラクターではなく、インスタンスも作成されていないと思います...関数のローカル変数はすぐに破棄されるべきではありません機能が完成しました?? それとも私の論理が間違っていますか?? 上記のコードで何が起こっているのですか?? 誰か説明してくれませんか....

私はここで私のコードのフィドルを作りました..

この愚かな質問をして申し訳ありません..

4

2 に答える 2

1

JavaScript クロージャへようこそ。行ごとに見てみましょう。

var first10 = Range(1,10);
var first10Odd = Range(1,20,2);

私たちはそれRangeが単なる関数であることを知っています。したがって、これらの 2 行では、Rangeそれぞれ 2 つと 3 つの引数を指定して関数を呼び出しています。

では、関数を呼び出すとどうなるでしょうか。明らかな答えは、関数の本体が実行されるということです。関数の本体には何がありますか。

if (step === undefined ) step = 1;

var arr = [], index = 0;

while(start <= end) {
  arr[index]  = start ;
  index += 1;
  start += step; 
}

上記の行が非常に明白であり、問​​題がないことを願っています。

var getAll = function () {
   return arr;
};

この行は何をしますか? 実行時に関数を作成します。なぜランタイム?例を見てみましょう。

<script>
   func1();
   var func1 = function() {
      alert("Hi");
   }
</script>

<script>
   func1();
   function func1() {
      alert("Hi");
   }
</script>

最初のスクリプト ブロックを使用すると、エラーがスローされます。なんで?まだ定義されていない関数を呼び出しています。2 番目のケースでは、JavaScript の解析時間自体で関数を定義しています。最初のケースで作成された関数のタイプは、無名関数と呼ばれます。に戻りましょうgetAllgetAllこれで、無名関数を指す単純な変数であることがわかりました。それが何をするか見てみましょう。返しますarrarrへのアクセス方法 関数の外で宣言されているため、引き続きアクセスできます。と同じケース

var getOne = function(n) {
  return arr[n] ;
};

今、非常に重要な部分、

  return function(i) { 
    if (i === undefined) {
       return getAll();
    } else {
       return getOne(i);
    }
  };

それは何をするためのものか?関数を返します。正確には、無名関数を返します。が呼び出されるたびRangeに、新しい無名関数が作成されます。この関数は、1 つのパラメーターを受け取り、それを返します。それで、今何をし、何first10first10Odd持っていますか?はい。そうです、それらには機能があります。それが説明できることを願っています

alert(first10);    // alerts - function(i) { ... }
alert(first10Odd); // alerts - function(i) { ... } 

両方の機能を調べてみましょう。first10が何も指定されていない場合first10()、つまり 、パラメータiの値は になりますundefined。したがって、実際にはパラメーターなしで無名関数を呼び出しており、それは を返すはずgetAll()です。はでfirst10作成されましたRange(1,10);。したがって、 はarrになります[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

関数から戻ったときに、関数内で宣言された変数がスコープ外に出ることはないと思うかもしれません。答えはイエスかノーです。単純に値を返す場合はイエスです。いいえ、関数を返すとき。関数を返すと、変数の状態が維持されます。このプロパティは と呼ばれclosuresます。それがそれが戻る理由です

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]     for alert(first10())
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] for alert(first10Odd())
1                                   for alert(first10(0))
19                                  for alert(first10Odd(9))

Closure の詳細については、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closuresをご覧ください。

于 2013-10-13T07:58:12.357 に答える