I'm trying to get my head round the revealing module pattern in javascript. I'm puzzled by two things about the following code snippet.
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); });
The three values written to the console here are 100, 150, 100. That tells me that when I call "addPoints" with a value the totalPoints variable isn't updated. If I examine the value of totalPoints within the addPoints function it has been incremented properly. What's going on?
If I use the console to examine window.addPoints or window.getPoints I can see that because I haven't used "var" in front of the function declarations they've been added to the global scope. Isn't that wrong? Most of the examples I'm looking at seem to do this.
Any pointers gratefully received.
The Revealing Module pattern is a design pattern for Javascript applications that elegantly solves this problem. The central principle of the Revealing Module pattern is that all functionality and variables should be hidden unless deliberately exposed.
Revealing module pattern is a design pattern, which let you organise your javascript code in modules, and gives better code structure. It gives you power to create public/private variables/methods (using closure), and avoids polluting global scope (If you know how to avoid that).
The Module Pattern is one of the most common design patterns used in JavaScript and for good reason. The module pattern is easy to use and creates encapsulation of our code. Modules are commonly used as singleton style objects where only one instance exists. The Module Pattern is great for services and testing/TDD.
Modules are an integral piece of any robust application's architecture and typically help in keeping the units of code for a project both cleanly separated and organized.
You're passing a number here:
return { points: totalPoints, addPoints: addPoints };
This piece of code is no different from:
return { points: 100, addPoints: addPoints };
You're passing the value; not a reference to totalPoints
(the latter is not possible in JavaScript). So when totalPoints
changes, the value in the object does not.
The simplest way to get around this is to use a function to get the most up-to-date result (like getPoints
which you already have). This JSFiddle gives a complete example:
return { points: function(x) { return totalPoints; }, // always up-to-date addPoints: addPoints };
The downside is that the caller must now ask for points
as a function call:
console.log(george.points());
Another solution is using getters which would enable you to get an updated value with just george.totalPoints
, though getters are not widely supported (yet). You could implement a getter like this:
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;
Secondly, dropping var
makes the functions global which is correct but not advisable. You could make one var
statement using commas, if that's what you mean:
var totalPoints = 100, // expands to three `var` statements, so no addPoints = ..., // global variables getPoints = ...;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With