我正试图在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”它们已被添加到全局范围。 这不是错吗?我正在考虑的大多数例子都是这样做的。
感激地收到任何指示。
答案 0 :(得分:31)
你在这里传递一个号码:
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
};
缺点是调用者现在必须要求points
作为函数调用:
console.log(george.points());
另一种解决方案是使用 getters ,将使您能够仅使用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 = ...;
答案 1 :(得分:0)
这是一个稍微不同的解决方案,它不需要getter / setter并将totalPoints
保留为属性。
var Child = function () {
var _api;
return _api = {
addPoints: addPoints,
points: 100
};
/* ----------- */
function addPoints(points) {
_api.points += points;
return _api.points;
};
};