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

5 回答 5

13

它保留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 闭包

于 2013-02-09T22:22:37.040 回答
5

这就是发生的事情:

  1. init() 函数对counter在 Test 范围内定义的变量进行了闭包,并持有对它的引用。
  2. Test() 函数的返回创建了一个新对象,其中另一个变量counter设置为 internal 的值counter
  3. 您通过设置 test1.counter = X 来更新“另一个” counter,但 init() 仍然包含对原始变量的引用。

这就是为什么你看到旧的价值。

于 2013-02-09T22:28:56.040 回答
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

在您的示例中,您没有将计数器设置为 Test 对象/函数上的属性,而是在调用时test1.counter实际上设置了一个以前不存在的新属性,并且您的 init 函数没有引用该属性。

正如德里克斯的回答所示,您似乎对我的回答和他的回答之间的两种不同模式略有混淆。

于 2013-02-09T22:21:36.380 回答
1
alert(test1.counter); // Alerts 0 ????? It's "0" because you call it before change counter to 5
test1.counter = 5;
alert(test2.counter); // Alerts 0 ????? It's "0" because you call it before change counter to 10
test2.counter = 10;
alert(test1.counter); // Alerts 5 | It's 5 because you call it AFTER change counter to 5
于 2020-03-05T14:48:15.563 回答
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
于 2016-09-25T00:23:11.270 回答