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 */

你能逐行解释这个代码吗?我明白一个;; 方法对变量计数器共享变量有一个评估,但无论如何它似乎很神奇,因为我们说它在开始时等于零

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从匿名函数访问时,结果将是window对象,但您无法使用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;
    }
  };   

这些仍然是 的“公共”方法Counter,它们是Counter对象范围的一部分。您可以像在警报中一样访问它们。

})();

这意味着该函数是自调用的,例如它正在立即执行。

现在,在我继续之前...当您启动脚本时,对象Counter被创建,因为它是一个自调用函数。这将创建该对象的范围和它的匿名函数的另一个范围(具有一个“私有”属性和一个“私有”方法)。三个返回的方法在 的范围内Counter,但它们可以访问它的匿名函数的范围,即使该函数已经返回。那是因为这三个方法都指向那个范围,它们仍然有“一些业务”,所以垃圾收集器不会触及内部变量。返回匿名函数后,您可以访问其中的值的唯一方法是通过它返回的方法(如果有的话)。希望这很清楚。现在,让我们继续。

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包含三个函数(incrementdecrement值)和一个变量( ), 初始化时设置为零,这很明显,但我认为让您很难将三个函数一起返回,但将其视为将它们包含在“计数器”中,现在三个函数中的每一个都返回值()或递增/递减某个数字. 现在最后 6 行应该是有意义的,第一行只是复制初始值为零,然后我们增加两次,函数将内部值增加两次到 2,当你再次执行时它变成 2,并且privateCounterprivateCountervalue()increment()value()decrement()做同样的事情。我希望我的谈话对你有意义。

于 2013-10-11T12:07:22.143 回答