Javascript, показывающий шаблон модуля, общедоступные свойства - программирование

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);
        });
  • Три значения, записанные на консоль здесь: 100, 150, 100. Это говорит мне, что когда я называю "addPoints" со значением, переменная totalPoints не обновляется. Если я изучу значение totalPoints в функции addPoints, он будет увеличен правильно. Что происходит?

  • Если я использую консоль для просмотра window.addPoints или window.getPoints, я вижу это, потому что я не использовал "var" перед объявлениями функций, которые они добавили в глобальную область. Не так ли? Большинство примеров, на которые я смотрю, похоже, делают это.

Любые указатели с благодарностью получили.

4b9b3361

Ответ 1

Вы передаете номер здесь:

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());

Использование геттеров и сеттеров

Другое решение - использовать геттеры, которые позволят вам получить обновленное значение только с помощью george.totalPoints, хотя получатели не поддерживаются (пока). Вы можете реализовать геттер следующим образом:

var obj = {};

obj.points = addPoints;

// add a "special" property to the object instead of normal notation
Object.defineProperty(obj, "totalPoints", {
    get: function() { // function that 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 = ...;

Ответ 2

Это немного другое решение, которое не требует установки getter/setter и сохраняет totalPoints как свойство.

    var Child = function () {

        var _api;

        return _api = {

            addPoints: addPoints,
            points: 100
        };

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

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

    };