25

我试图让我的头脑了解 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”,它们已被添加到全局范围。那不是错了吗?我正在查看的大多数示例似乎都是这样做的。

任何指点都感激不尽。

4

2 回答 2

33

你在这里传递一个数字:

return {
    points: totalPoints,
    addPoints: addPoints
};

这段代码与:

return {
    points: 100,
    addPoints: addPoints
};

您正在传递价值;不是引用totalPoints(后者在 JavaScript 中是不可能的)。所以当totalPoints改变时,对象中的值不会。


使用函数

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

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

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

console.log(george.points());

使用 getter 和 setter

另一种解决方案是使用getter,这将使您能够使用 just 获得更新的值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 = ...;
于 2012-01-17T10:44:18.193 回答
0

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

    var Child = function () {

        var _api;

        return _api = {

            addPoints: addPoints,
            points: 100
        };

        /* ----------- */

        function addPoints(points) {
            _api.points += points;
            return _api.points;
        };

    };
于 2015-03-20T12:31:35.230 回答