2
    var Counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };   
})();

alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */

このコードを1行ずつ説明してもらえますか? 私はそれを理解しています;; メソッドには変数カウンター共有変数へのロバがありますが、とにかく魔法のように思えますが、最初はゼロに等しいと言っているからです

4

3 に答える 3

2

Javascript はスコープがすべてです。Counterそのコードは、直接ではなく呼び出される変数でオブジェクトを定義します。オブジェクトを返す関数を定義して呼び出します (メソッドincrement()decrement()、および を使用value())。そのオブジェクトのスコープはそれが作成された場所であるため、最初は無名関数本体であり、次にグローバル名前空間です。クロージャーは宣言 (格納) されておらず、一度だけ呼び出されますが、スコープは残ります。オブジェクトが変数privateCounterとメソッドにアクセスできるようにしますchangeBy()。また、これらのメンバーにアクセスできる唯一のオブジェクトであるため、「プライベート」と呼ばれます。

于 2013-10-11T12:00:19.740 に答える
1
var Counter = (function() {

これは、 という名前のオブジェクトの作成ですCounter。匿名の自己呼び出し関数によって作成されます。ただし、関数は自己呼び出しであるため、大文字の名前を付けることはお勧めしません。

  var privateCounter = 0;

「プライベート」変数privateCounterが設定されています。外部から直接アクセスできないという意味でプライベートです。これは無名関数のスコープで作成され、それを含む関数とは別のスコープを与えます - Counter。これが、外部からアクセスできない理由ですCounter.privateCounter === undefined。注:this無名関数からアクセスしようとすると、結果はwindowobject になりますが、 ではアクセスできませんwindow.privateCounter

  function changeBy(val) {
    privateCounter += val;
  }

これは「プライベート」メソッドですCounter.changeBy() === undefined。するのと同じvar changeBy = function(val){}です。プロパティまたはメソッドを「パブリック」(外部からアクセス可能) にしたい場合は、次のように定義する必要があります。

this.publicCounter = 0;
this.changeBy = function(val)...

これは、オブジェクトが無名関数を介して作成されていない場合の通常の方法です (上のコメントを確認してくださいthis)。この場合、次のように作成します。

  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };   

これらは の「パブリック」メソッドのままであり、 objectCounterのスコープの一部です。Counterアラートと同じようにアクセスできます。

})();

これは、関数が自己呼び出しであることを意味します。たとえば、すぐに実行されます。

さて、先に進む前に... スクリプトを開始するCounterと、自己呼び出し関数であるため、オブジェクトが作成されます。これにより、そのオブジェクトのスコープと、その匿名関数の別のスコープが作成されます (1 つの「プライベート」プロパティと 1 つの「プライベート」メソッドを使用)。返された 3 つのメソッドは のスコープにありCounterますが、関数が既に返されていても、その無名関数のスコープにアクセスできます。これは、これら 3 つのメソッドがそのスコープを指しているためであり、そこにはまだ「ビジネス」があり、ガベージ コレクターは内部変数に触れません。匿名関数が返された後、その内部の値にアクセスできる唯一の方法は、返されたメソッド (存在する場合) を使用することです。これが明確であることを願っています。では、先に進みましょう。

alert(Counter.value()); /* Alerts 0 */

これは、オブジェクトvalue()のメソッドを呼び出しCounterます。このメソッドは、既に返された無名関数のスコープに到達し、ローカル変数の値を返します。

Counter.increment();
Counter.increment();

再び、返された関数内のローカル関数にアクセスできるオブジェクトの「パブリック」メソッドを呼び出します。

alert(Counter.value()); /* Alerts 2 */

従来通り。ただしprivateCounter、すでに返された関数のスコープ内にあることに注意してください。新しいものを作成するのではなく、まだそれを見る独占的な権利を持ついくつかの方法で古いものにアクセスしているだけです。

Counter.decrement();
alert(Counter.value()); /* Alerts 1 */

従来通り。

基本的に、便利屋 (オブジェクト) を呼び出すようなもので、便利屋には常にスキル (「パブリック」メソッドとプロパティ) とツール (「プライベート」メソッドとプロパティ) が付属しています。何かをする必要がある場合は、便利屋に電話して、何をすべきか、どのスキルを使用するかを伝えますが、彼なしでは彼のツールを使用することはできません. そして、彼はツールのコレクションを持っています。電話をかけるたびに新しいセットを購入することはありません。彼のペンチは、あなたが踏んで壊れたのと同じ古いペンチです。

于 2013-10-11T14:23:14.033 に答える
0

それは非常に簡単です、私はそれをより明確にしようとし ますcounter. 、しかし、3つの関数を一緒に返すのが難しくなったと思いますが、それらを「カウンター」に含めると考えてください。3つの関数のすべてが値()を返すか、特定の数だけインクリメント/デクリメントします. これで、最後の 6 行が意味をなすはずです。最初の行は初期値のゼロをコピーするだけです。次に 2 回インクリメントし、関数は内部値を 2 回インクリメントして 2 にします。もう一度実行すると 2 になります。incrementdecrementprivateCounterprivateCountervalue()increment()value()decrement()同じことをします。私の話があなたにとって意味のあるものであることを願っています。

于 2013-10-11T12:07:22.143 に答える