4

私はプログラミングのクロージャの概念、特にJavascriptに関連するものをより具体的に読んでいます。私が何年も書いてきた Javascript コードとどのように違うのか、まだ完全には理解できていません。再帰の概念も理解していますが、クロージャーと再帰はどのように似ているのでしょうか? 再帰自体がクロージャーの一種であることを正しく理解していますか?

閉鎖:

function init() {
    var name = "Stack Overflow";
    function displayName() {
        alert(name);
    }
    displayName();
}
init();

再帰:

function factorial(num) {
    if(num < 0)
        return -1;

    else if(num == 0)
        return 1;

    else
        return (num * factorial(num - 1));
}

alert(factorial(8));

クロージャーとは関数内に関数を持ち、内部関数がスコープを介して外部関数にアクセスできることを理解し始めていると思います。再帰的なクロージャはありますか? つまり、私の再帰の例はクロージャーの例でもありませんが、少なくともそれは起こり得るのでしょうか? 私は、再帰とクロージャーがどのように似ているか、異なっているか、またはそれらがすべて比較できるかどうかを理解しようとしています。これを説明する例はありますか?

4

2 に答える 2

9

クロージャは、単に環境 (本体) を「閉じる」関数または手順です。あなたのコードではinit、 、displayName、およびfactorialはすべてクロージャーです。クロージャを作成するときは、 JavaScriptfunctionキーワード (または=>、ES6 にはアロー関数があります) を使用します。

再帰は、手順が繰り返される結果です


私は新しい本を読んでいて、いくつかの関連トピックについて語っています。興味がある場合に備えて、ここでいくつかのメモを共有したいと思いました。

これは、階乗を計算するための再帰関数です。それはあなたのものと同じことをしますが、非常に異なる方法で行います。どれどれ!

function factorial(x) {
  if (x < 0) throw Error("Cannot calculate factorial of a negative number");
  function iter(i, fact) {
    return i === 0 ? fact : iter(i-1, i*fact);
  }
  return iter(x, 1);
}

factorial(6); // 720

上で定義した^.^と比較してください。factorial再帰的ですが、自分自身 ( ) を再度呼び出さないことに注意してください。これは、直線的な空間と時間を消費する直線的な反復プロセスを使用します。関数の評価はこんな感じ

factorial(6);
  iter(6, 1);
  iter(5, 6*1); 
  iter(4, 5*6);
  iter(3, 4*30);
  iter(2, 3*120);
  iter(1, 2*360);
  iter(0, 1*720);
// => 720

それを関数のプロセスと比較してください。あなたの場合は次のようになります

factorial(6);
(6 * factorial(5));
(6 * (5 * factorial(4)));
(6 * (5 * (4 * factorial(3))));
(6 * (5 * (4 * (3 * factorial(2)))));
(6 * (5 * (4 * (3 * (2 * factorial(1))))));
(6 * (5 * (4 * (3 * (2 * 1)))));
// => 720

n増加すると、n!別のスタック呼び出しが追加されることに注意してください。これは線形再帰プロセスです。の値が大きい場合n、このメソッドは同じ結果を計算するためにかなり多くのスペースを使用します。

于 2015-04-21T05:44:23.400 に答える