我正在尝试了解 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);
});
此处写入控制台的三个值是 100、150、100。这告诉我,当我使用某个值调用“addPoints”时,totalPoints 变量不会更新。如果我检查 addPoints 函数内的 TotalPoints 值,它已正确增加。 发生什么事了?
如果我使用控制台检查 window.addPoints 或 window.getPoints,我可以看到这一点,因为我没有在函数声明前面使用“var”,它们已被添加到全局范围中。 这不是错误的吗?我正在查看的大多数示例似乎都是这样做的。
非常感谢您的指点。
最佳答案
您在此处传递一个数字:
return {
points: totalPoints,
addPoints: addPoints
};
这段代码与:
return {
points: 100,
addPoints: addPoints
};
您正在传递值;不是对 totalPoints
的引用(后者在 JavaScript 中是不可能的)。因此,当 totalPoints
发生变化时,对象中的值不会发生变化。
使用函数
解决此问题的最简单方法是使用函数来获取最新结果(例如您已有的 getPoints
)。 This JSFiddle给出一个完整的例子:
return {
points: function(x) { return totalPoints; }, // always up-to-date
addPoints: addPoints
};
缺点是调用者现在必须以函数调用的形式请求点
:
console.log(george.points());
<小时/>
使用 getter 和 setter
另一个解决方案是使用getters,它使您能够仅使用george.totalPoints
获得更新的值,尽管getters没有得到广泛支持(然而)。您可以像这样实现 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 = ...;
关于Javascript 揭示模块模式、公共(public)属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8893099/