Because JavaScript uses prototype-based inheritance, there is no keyword to define a member as “private” or “protected”. Either the object has a member, or it doesn’t, and you can access that member from anywhere you can access the object. Do not despair! There is a way to implement private variables… using another feature of the language: closures!
Closures
Closures are fairly simple, but frequently misunderstood. What you need to know for now, is that a closure allows you to reference an outer variable from within a function, even when the function is called from another context.
This will make more sense when you see some code.
function countup() { var count = 0; // private variable, only accessible within this function return function iterate() { // return newly defined function return ++count; // referencing variable from outer scope } }; var iterate = countup(); iterate(); // 1 iterate(); // 2 iterate(); // 3 // etc.
Another important aspect of closures, is that a new one is created with every function definition, even when that function definition is nested. Here is an illustration of that.
function countup() { var count = 0; // private variable, only accessible within this function return function iterate() { // return newly defined function return ++count; // referencing variable from outer scope } }; var iterate1 = countup(); // every time countup() is called... var iterate2 = countup(); // a new private variable "count" is created // a new private function called "iterate" is defined // which causes a new closure to be created with that // new private function, and its environment iterate1(); // 1 iterate1(); // 2 iterate2(); // 1 // points to a different closure, with a different internal "count" variable iterate2(); // 2
You can probably see where this is going.
Private Members
Using this knowledge, you can probably already see how to create variables that are not accessible from outside of an object, but can be used by the methods of that object. These private members can be variables or functions.
function Dance() { function shakeHips() { alert('Hips are shaking!'); } function moveArms() { alert('Arms are moving!'); } function getDown() { alert('Getting down tonight!'); }; var inTheGroove = false; this.Boogie = function() { if (!inTheGroove) { shakeHips(); moveArms(); getDown(); inTheGroove = true; } else { alert("Like, I'm already in the groove, man!"); } }; } var dancer = new Dance(); //dancer.inTheGroove; // undefined dancer.Boogie();
There are a few different ways to accomplish this. Above is probably the most simple. If you have ever written (or read the source code for) a jQuery plugin, you have probably seen something like this:
(function(window) { // this variable and these functions are private to this function var inTheGroove = false; function shakeHips() { alert('Hips are shaking!'); }, function moveArms() { alert('Arms are moving!'); }, function getDown() { alert('Getting down tonight!'); }, function Dance() { } Dance.prototype = { Boogie: function() { if (!inTheGroove) { shakeHips(); moveArms(); getDown(); inTheGroove = true; } else { alert("Like, I'm already in the groove, man!"); } } } window.Dance = Dance; })(window); var dancer = new Dance(); dancer.Boogie();
Good stuff, though I prefer the revealing module pattern. So many ways to skin the cat in JS!
The revealing module pattern is good for a lot of things, but you need to be a little more careful with your inheritance. If you override any of the “revealed” members, you get potentially inconsistent behavior, since all of the private members are still pointed at the original members, not the overridden ones.
Other than that, I agree. The revealing module pattern is a little easier to read.
Comments are closed.