2013-02-09 8 views
15

私はJavaScriptをかなりよく理解し始めていると思っていましたが、はっきりとは分かりませんでした。私の問題点の例を説明しましょう。まず私は、次のモジュールが定義されている:(それが公開されているとして) モジュールの複数のインスタンスを作成する

var test1 = new Test(); 
var test2 = new Test(); 

は、今私は、カウンタ変数を更新し、いくつかの警告を行います。私は、2つのインスタンスを作成

var Test = function() { 
    var counter = 0; 

    function init() { 
     alert(counter); 
    } 

    return { 
     counter: counter, 
     init: init 
    } 
}; 

。ここまでは順調ですね。

alert(test1.counter); // Alerts 0 
test1.counter = 5; 
alert(test2.counter); // Alerts 0 
test2.counter = 10; 
alert(test1.counter); // Alerts 5 

は今、最終的に私は次のように言う:

test1.init(); // Alerts 0 
test2.init(); // Alerts 0 

これは私が理解していないビットです。なぜこの警告は0ですか?私は最初の警告が5と2番目の10であると思った。

誰かが上記の仕組みを説明して正しい方向に向ける方法があれば、私は感謝します。おかげ

+4

スカラ変数が参照ではなく値によって渡される入力されました。だから 'return {counter:counter、...}'は現在の 'var counter 'の値をコピーし、' this.counter'を変更するだけで 'var counter'には影響しません。 –

答えて

11

これは、Test内の変数を変更していないため、この関数によって返されたオブジェクトが変更されているためです。0はそのままです。 counterは「プライベート」に保たれ、Testの機能だけがアクセスできます。

var Test = function() { 
    var counter= 0; 

    function init() { 
      alert(counter); 
    } 
    function changeNum(n){ 
     counter = n;   //add a function inside `Test` so that it can 
    }       //access the variable 

    return { 
     counter: counter, 
     init: init, 
     changeNum: changeNum 
    } 
}; 

は、今では動作します: http://jsfiddle.net/DerekL/pP284/

var test1 = new Test(); 
alert(test1.counter);   //0 
test1.init();     //0 
test1.changeNum(5); 
alert(test1.counter);   //5 
test1.init();     //5 

詳細については、JavaScript Closuresを参照してください。

+0

多くのありがとう。これにより、うまくクリアされました。 – nfplee

+0

なぜ、すべてのスクリプトで使用できるグローバルスペースでテストできるのでしょうか? – AntonioRomero

3

あなたの記事でミスを犯している場合、私はわからないが、あなたは上の財産であることをカウンタを設定していないあなたの例では

var Test = function() { 
    this.counter = 0; 
} 

Test.prototype.init = function() { 
    alert(this.counter); 
} 

var test1 = new Test(); 
var test2 = new Test(); 


test1.counter = 5; 
test2.counter = 10; 

test1.init(); // alerts 5 

test2.init(); // alerts 10 

を次のように、あなたは上記のコードを書き換えることができテストオブジェクト/関数ではなく、test1.counterを呼び出すと、以前は存在しなかった新しいプロパティが設定され、init関数はそのプロパティを参照していません。

デレックスの答えが示すように、あなたは私の答えに続くものと彼の次の2つの異なるパターンを少し混乱させたようです。

5

これは何が起こったかである:

  1. のinit()関数は、それへの参照を保持し、試験範囲内で定義されcounter変数に閉鎖しました。
  2. Test()関数からの戻り値が新しいオブジェクトを作成しました。別の変数counterが内部counterの値に設定されています。
  3. test1.counter = Xを設定して 'another' counterを更新しますが、init()は元の変数への参照を保持しています。

これで、古い値が表示されます。ここで

+0

余分な説明をありがとう。私はDerekにあなたの前に来て、それが私を助けてくれたという理由だけで、Derekに答えを与えました。 – nfplee

0

は、私がどうなるのかです:

function Test() { 
    this.counter = 0; 
    this.init = function() { console.log(this.counter); } 
}; 

var test1 = new Test(); 
var test2 = new Test(); 

console.log(test1.counter); //0 
test1.counter = 5; 
console.log(test2.counter); //0 
test2.counter = 10; 
console.log(test1.counter); //5 

test1.init(); //5 
test2.init(); //10 
関連する問題