2013-02-09 161 views
15

我以爲我開始很好地理解JavaScript,但顯然不是。讓我用一個例子來解釋我的問題。首先,我已經定義了以下模塊:創建模塊的多個實例

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

    function init() { 
     alert(counter); 
    } 

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

我再創建2個實例:

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

現在我更新計數器變量(因爲它是公開的),並做一些提醒。到現在爲止還挺好。

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和第二個10.

我會很感激,如果有人能解釋如何可以工作或指出我在正確的方向。由於

+4

標量類型的變量是按值而不是按引用傳遞。所以'return {counter:counter,...}'只是複製當前的'var counter'值並改變'this.counter'不會影響'var counter'。 – 2013-02-09 22:28:25

回答

11

它保持0是因爲你沒有改變Test裏面的變量,你正在改變函數返回的對象。 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 2013-02-12 22:50:33

+0

爲什麼可以測試全局空間可用於所有腳本? – AntonioRomero 2015-04-10 09:28:35

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函數並沒有引用那個屬性。作爲小企業的回答表明,你似乎對我的回答和他的回答之間的兩種不同模式有些困惑。

5

這是所發生的事情:

  1. 的init()函數取得的counter變量,它內部的測試範圍限定的閉合,保持它的一個引用。
  2. Test()函數的返回值創建了一個新對象,其他變量counter設置爲內部值counter
  3. 您通過設置test1.counter = X來更新'another'counter,但init()仍保留對原始變量的引用。

這就是爲什麼你會看到舊的價值。

+0

感謝您的額外澄清。我僅僅因爲他在你之前來到德雷克就給了他答案,這同樣幫助了我。 – nfplee 2013-02-12 22:50:07

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