Private Variables In Java Script

[From JavaScriptCodingStandard]

JavaScript has private variables, here's proof:

  function SomeClass(){
    var aPrivateVar="private";  //private member
    this.PublicVar="public";  //public member

this.GetPrivateVar=function(){ //accessor for private member return aPrivateVar; } }

var anInstance = new SomeClass(); alert(anInstance.PublicVar); -> "public"; alert(anInstance.aPrivateVar); -> undefined; //see, no access to private variable, aren't closures great. alert(anInstance.GetPrivateVar()); -> "private";

This page is mostly a misunderstanding of how JavaScript works.

Since there is no private keyword in JavaScript, we should ensure by naming convention that methods that are intented to be private are not used outside. So, all methods and variables that are to be private should have the following format <ClassName>_<methodName>. For e.g.

Utils.showMessage = Utils_showMessage;

function Utils_showMessage() { alert("Hello World!"); }

Here method will be called as"Utils.showMessage()"

-- VhIndukumar

This is interesting. Actually I find this useful for all member functions: it clearly states which are intended for each class... Functions without the <ClassName>_ part can obviously be generic, ie. for all classes, and the distinction between private and public should be solved in the declaration itself:

Public_<ClassName>_<functionName> for public methods
Private_<ClassName>_<functionName> for private ones.

When exposing the object to programmers, public member functions should always go first, and properly tagged with a comment. Same for private ones (this has to do with SelfDocumentingCode):

// PUBLIC
Foo.getValue = Public_Foo_getValue;

function Public_Foo_getValue() { /* ... */ } // and so on...

On the other hand, JavaScript does has private and public variables... Please see this article by Douglas Crockford at http://www.crockford.com/javascript/private.html [updated URI] --DavidDeLis

That article by DouglasCrockford is really interesting. Thanks for the pointer. -- AnonymousDonor

All modern browsers (JavaScript 1.2+ and equivalent) support literal anonymous functions. This is, IMHO, a much more elegant way to define methods. Sure, anonymous functions are in the language specs, and (among other things) they are there to allow this definition; function () {} is actually a lambda function in disguise. I recall, though, that the latest version of the NGS JavaScript interpreter/compiler didn't support it (bummer)... Actually, it's just a lambda function; it's not in disguise. A disguised one would be function foo() {} if anything. --DanielBrockman

Also, I like to prefix my private/protected members with an underscore, to easily spot bad code using private members of other classes. I format my code rather unconventionally; if you think it's awkward, please disregard it in favour of the actual code.

/* Analogous to extends SomeBaseClass: */
SomeClass.prototype = new SomeBaseClass();
SomeClass.prototype.constructor = SomeClass;
function SomeClass() {
/* Analogous to super(foo, bar): */
SomeBaseClass.call(this, foo, bar);

this._somePrivateField = 123;

}; SomeClass.prototype.somePublicInstanceMethod = function() {

}; SomeClass.prototype._somePrivateInstanceMethod = function() {

}; SomeClass.somePublicClassMethod = function() {

}; SomeClass._somePrivateClassMethod = function() {

};

-- DanielBrockman

I find this way of formating the code very interesting (btw, I prefer privateVar_). Indentation clearly delimits the scope of each operation and the intention of their use... Maybe gathering from the mother page and what's been said in here, proper exposure to the object's API can be achieved in a very clear way. Let's give it a first shot:

// a Foo...
function Foo( bar, baz ) {
// PUBLIC
this.name = bar;
this.size = baz;

this.publicClassMethod = function ( boo ) { // stuff... };

// private var count_; var secret_;

// PRIVILEDGED var self = this;

this.priviledgedAddOne = function () { self.count_++;

// PRIVATE }; function private () { // ...

// PUBLIC }; Foo.prototype.getFoo = function () { // ... }

Sorry, but I have to say I don't understand much of the above code. How is publicClassMethod a public class method; why is Foo.prototype.getFoo defined inside the constructor; are we supposed to duplicate the "priviliged" methods in every subclass; and won't it be annoying that public methods won't be able to access access private members? -- DanielBrockman


The above code is redundant, and in some sense, Wrong. Prototype functions in JavaScript need be declared only once, then never again. It is wrong to assign the function prototype at constructor time. You should be doing it this way:

function MyClass ()
{
// ... my constructor code ...
}

function MyClass.prototype.MyPublicMethod () { // ... }

My comment is not addressed to method/member accessibility, but simply to the way that member functions are assigned to classes (not just instances). At the core is the realization that, in JavaScript, these two statements are nearly identical:

function SomeFunction ()
{
...
}

var SomeFunction = function () { ... }

Therefore, "function SomeClass.prototype.SomeMethod () { ...} " is equivalent to assigning to SomeClass.prototype.SomeMethod. The crucial difference is that you don't need to execute any code for the "function Foo () { ... }" form to update the value of Foo -- the value is updated just after the code block is lexically analyized, but before the JScript engine actually executes any code. This is something of a cheat, but it is a very useful cheat.

-- ArlieDavis

I believe you are wrong. They are not equal because of the lexical environment. A function delcared inside the constructor has access to the private members of that constructor essentially building a closure with private members... a function declared outside and added later doesn't, it's a huge difference.

Wow -- I didn't know "function a.b () {}" was legal, and honestly can't believe I never tried it. Unfortunately, I don't have access to an implementation to try it out right now. Did it always work? (BTW, Arlie, I added a "var" to your latter code snippet; hope you don't mind!) -- DanielBrockman

It isn't legal. It's a Microsoft extension that works only in JScript.


Since there is no private keyword in JavaScript, we should ensure by naming convention that methods that are intented to be private are not used outside.

Naming conventions do not ensure anything. It only takes one person who does not understand your private naming rules for the "guarantee" to fall apart. Rather, adopt the following coding rules:

  1. Never access a variable outside of its class (basic OO presumption)
  2. Instead of private methods, encapsulate the non-public methods into their own class(es) and add them as object variables to the desired class.


CategoryJavaScript


EditText of this page (last edited December 28, 2009) or FindPage with title or text search