Javascript揭示模块模式,公共属性

我试图在javascript中绕过揭示模块模式。 我对以下代码片段的两件事感到困惑。

var Child = function () { var totalPoints = 100; addPoints = function (points) { totalPoints += points; return totalPoints; }; getPoints = function () { return totalPoints; }; return { points: totalPoints, addPoints: addPoints }; }; $(function () { var george = Child(); console.log(george.points); console.log(george.addPoints(50)); console.log(george.points); }); 
  1. 这里写入控制台的三个值是100,150,100。这告诉我,当我用值调用“addPoints”时,totalPoints变量不会更新。 如果我检查addPoints函数中totalPoints的值,它正确递增。 这是怎么回事?

  2. 如果我使用控制台来检查window.addPoints或window.getPoints,我可以看到,因为我没有在函数声明前面使用“var”它们已被添加到全局范围。 那不是吗? 我正在看的大多数例子似乎都是这样做的。

任何指针都感激不尽。

你在这里传递一个号码:

 return { points: totalPoints, addPoints: addPoints }; 

这段代码与以下内容没有区别:

 return { points: 100, addPoints: addPoints }; 

你传递了价值 ; 不是对totalPoints的引用(后者在JavaScript中是不可能的)。 因此,当totalPoints发生更改时,对象中的值不会更改。


使用function

解决这个问题的最简单方法是使用函数来获得最新的结果(比如你已经拥有的getPoints )。 这个JSFiddle给出了一个完整的例子:

 return { points: function(x) { return totalPoints; }, // always up-to-date addPoints: addPoints }; 

缺点是调用者现在必须要求points作为函数调用:

 console.log(george.points()); 

使用getter和setter

另一个解决方案是使用getter ,它可以让你只用george.totalPoints获得更新的值,尽管getter还没有被广泛支持。 你可以像这样实现一个getter:

 var obj = {}; obj.points = addPoints; // add a "special" property to the object instead of normal notation Object.defineProperty(obj, "totalPoints", { get: function() { // function that's executed when you use `.totalPoints` return totalPoints; } }); return obj; 

其次,删除var会使函数全局化,这是正确但不可取的。 您可以使用逗号创建一个var语句,如果这是您的意思:

 var totalPoints = 100, // expands to three `var` statements, so no addPoints = ..., // global variables getPoints = ...; 

这是一个稍微不同的解决方案,它不需要getter / setter并将totalPoints保留为属性。

  var Child = function () { var _api; return _api = { addPoints: addPoints, points: 100 }; /* ----------- */ function addPoints(points) { _api.points += points; return _api.points; }; };