I've been coding like mad lately - pulling together code in Javascript, HTML and C++ for the web APIs that we're working on.
See my other posts: here and here for more context.
One thing that had been nagging me about my own practice coding in javascript is that I still hadn't started implementing javascript objects with private data and functions. I knew it was possible but since the actual code layout was not obvious (at least as obvious as in C++) I procrastinated.
I'm happy to say I'm now creating my objects with private data and functions. I learned how to do this by reading this page by Douglas Crockford and by practicing the technique in a real project I'm working on.
Why do I want private data and methods in javascript?
I want them because I want to hide internal data and functions that implement the core functionality of my object behind a clean public interface. I want to disallow other code from changing my object's internal implementation except for the cases that have been explicitly allowed *through a public interface*.
I believe this also helps improve security because although a malicious script can change a public function of an object by assigning a different one to the same name; it can't change private functions and the private data and private function references they use.
I can always learn more about both javascript and security, so please feel free to help me along - especially with tips and tricks about defensive programming in javascript and web apps.
So, without further ado, here is some example code. This is a javascript object that includes both public functions and private functions and data:
FYI - I've updated this code based on Ruud's comment below and the link with Chris Heilmann's solution.
See my other posts: here and here for more context.
One thing that had been nagging me about my own practice coding in javascript is that I still hadn't started implementing javascript objects with private data and functions. I knew it was possible but since the actual code layout was not obvious (at least as obvious as in C++) I procrastinated.
I'm happy to say I'm now creating my objects with private data and functions. I learned how to do this by reading this page by Douglas Crockford and by practicing the technique in a real project I'm working on.
Why do I want private data and methods in javascript?
I want them because I want to hide internal data and functions that implement the core functionality of my object behind a clean public interface. I want to disallow other code from changing my object's internal implementation except for the cases that have been explicitly allowed *through a public interface*.
I believe this also helps improve security because although a malicious script can change a public function of an object by assigning a different one to the same name; it can't change private functions and the private data and private function references they use.
I can always learn more about both javascript and security, so please feel free to help me along - especially with tips and tricks about defensive programming in javascript and web apps.
So, without further ado, here is some example code. This is a javascript object that includes both public functions and private functions and data:
FYI - I've updated this code based on Ruud's comment below and the link with Chris Heilmann's solution.
/* CODE START - spell checker off :) ---------------------------------------*/
/* ObjectWithPrivates
A javascript object with public and private data and functions */
function ObjectWithPrivates(){
/* assign 'this' to 'that' so private functions can access this as that.
Confusing? just remember: "this, that it's all the same!" :)
From Doug Crockford's page:
This is a workaround for an error in the ECMAScript Language
Specification which causes this to be set incorrectly for inner
functions.
Note that I don't actually use the 'that' variable in
the code below because my private functions use the privfuncs, privdata
and pubfuncs containers to get at stuff. In any case, its a good
convention to follow so that private functions can access 'this'
through 'that' */
var that = this;
/* container for private data - organizational thing -
remember, since variables are scoped to the function block in
javascript all inner functions inside this function, our object's
constructor, have access to it. the outside world does not.
tada private data! */
var privdata = {
'data1':'this is some private data - data1',
'data2':'some more private data - data2'
};
/* private function container
mainly for code organization and readability */
var privfuncs = {};
/* public function container
we want private functions to be able to call public
functions, but they should only do this through this container
because the container can't be modified by the outside world directly!
Note below we can pick and choose which funcs from pubfuncs we
reveal through the array that we return.
*/
var pubfuncs = {};
/* public shared data container.
This seems to be needed so that both internal and external code can modify shared
data and see each other's changes. I've found that just using non array/object
types doesn't work. This is sort of redundant becuase all of this data could
just be revealed through this, but returning it through the array below
makes it much more clear what the public interface is ..and that is a good thing*/
var pubdata = {};
/* a private function - just displays a message */
privfuncs.priv_func_1 = function(){
alert("look everyone, this object has privates! - priv_func_1");
}
/* another private function - calls a public function
through the pubfuncs container.
This will call the correct pub_func_2() even if some other code
changes this.pub_func_2 from outside. Cool eh? */
privfuncs.priv_func_2 = function(){
/* always call the correct pub_func_2() */
pubfuncs.pub_func_2();
}
/* a public function - just calls some private functions */
pubfuncs.pub_func_1 = function(){
privfuncs.priv_func_1();
privfuncs.priv_func_2();
}
/* second public function - displays a message */
pubfuncs.pub_func_2 = function(){
alert("I'm the original pub_func_2() - private data: " + privdata['data1']);
}
/* Now for the public interface.
Return an array that reveals the public interface - nice and obvious what is public*/
return {
pub_func_1:pubfuncs.pub_func_1,
pub_func_2:pubfuncs.pub_func_2,
shdata:pubdata
}
}
/* Lets play with our object and its privates...
Be sure to look at 'obWithPrivs' in a dom inspector tool like the
one that comes with firebug. Wow, no public data members, just the
public functions! */
var obWithPrivs = new ObjectWithPrivates();
/* cheezy way to inspect the members of the object without
a proper dom inspector tool*/
for (var membr in obWithPrivs){
alert("found: obWithPriv." + membr);
}
/* call a public function */
obWithPrivs.pub_func_1();
/* okay - be evil and and install a new pub_func_2 from the outside
then call pub_func_1() again ...becuase we know it calls private code
that calls pub_func_2 internally */
obWithPrivs.pub_func_2 = function(){
alert("I'm the evil pub_func_2");
}
/* the new, evil, pub_func_2() will NOT be called from
the private code becuase the private code still references
the original pub_func_2()*/
obWithPrivs.pub_func_1();
/* the new, evil, pub_func_2() can still be called from the outside - but
it wasn't able to chain itself to the private functionality ! */
//alert("calling pub_func_2 directly...");
//obWithPrivs.pub_func_2();
/* CODE END ------------------------------------------------------------*/

Comments
There is a similair solution described by Chris Heilmann here: http://www.wait-till-i.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/
He named it the Revealing Module Pattern and in my opinion its a better solution.
As for that=this, i don't think its a work-around for an -error- in the ECMA specification.
You do indeed need that=this if you want to access the parent function but thats because of closures and it should work like that.
But correct me if im wrong :-)
/Ruud
Hey Ruud - GREAT link!. Thanks for that.
What I'm seeing in that code is the better way to do the pubfuncs by essentially returning a reference to an array with both public functions and data instead of adding the funcs from pubfuncs to this[pubref]. That is an elegant way to avoid the name conflict issue and allows us to return both public data and functions at once. Nice.
I still like the idea of the internal object implementation spelling out pubfuncs, privfuncs and privdata explicitly for readability ;)
Re: that = this - Doug Crockford said it was an error in ECMAScript - I'm guilty of repeating that as gospel here. Sounds like you have a different take on spec error vs no error?
I've updated the example code above based on Ruud's comment and link to Chris Heilmann's post.
Nice to see that you have updated the post :)
There's a new method for creating JavaScript private instance state: http://www.codeproject.com/KB/ajax/SafeFactoryPattern.aspx