As you know JavaScript has no concept of private members in objects. Objects there are “racks of properties” that anyone can change.
Here is a simple way of making “objects” in JS that have private instance variables. Such variables can be changed only by [public] methods you provide.
Consider following code:
function CreateMyObject() { var m_first = 0; var m_second = 0; var envelope = // our public interface { getFirst: function() { return m_first; }, setFirst: function(v) { m_first = v; }, getSecond: function() { return m_second; }, setSecond: function(v) { m_second = v; } }; return envelope; } var f = CreateMyObject(); var n = f.getFirst(); // calling our methods
Here we have CreateMyObject()
that behaves as a constructor of our object. It returns envelope object that has four methods. Only these methods can update or retrieve state of m_first and m_second variables. There are literally no other ways to access them from anywhere else other than set of methods provided.
Under the hood: In this example each interface method that we’ve created is a closure in fact: such methods have access to environment of outer function (CreateMyObject in this case) so they can access variables in this environment. Making a closure can be a memory expensive operation so avoid their use when you expect many instances of such objects.
The idea is neat. the only issue I can see here is the code can be use “new” keyword to initilize the object. anyway, we can claim we are using factory pattern here.
Take a look on Mike Koss article at: http://mckoss.com/jscript/object.htm
Basic idea is the same but you will be able to use “new”:
In original article we indeed have ‘no use’ of ‘new’ :
In fact above we (almost) have what is today called ‘javascript namespaces’. Which are absolutely important for any serious javascript app. This important implementational JS pattern may be described as:
This way we have a familiar and very important mechanism of paritioning large(r) javascript code. Also this idiom is more memory efficient than standard object made with ‘new’ keyword.
Regards: Dusan
My previous comment was somewhat too quick. Here is the complete explanation with javascript specific caveats.
JS Namespaces are (of course) nothing like namespaces which are part of other languages. In JS case this is just an implementational pattern which helps (but not completely) to do necessary paritioning of the larger JS apps. JS namespaces are only JS objects.
Here is a little javascript which might explain clrealy the pros and cons of JS namespace.
Pay attention that when you do call:
then
this
environment variable inside the function is a global namespace object.So second call:
will override ‘O’ and will return the same global object – default namespace.
Thus
is just
And yet each call of namespace() will create its own copy of
var counter
(in call frame).Andrew,
Thank you for your remark. The code shows that I know when n1 and n2 will share the same instnce of namespace() and when they will not. Please see the last portion in the javascript in my comment:
Also please run the code. And optionally follow it through a debugger.
Each call of namespace() will NOT create its own copy of var counter (in a call frame).
First for() loop will output values which will prove that var counter is shared. Same as O.counter. Sometimes there are situations when this is actually a desired behaviour.
But each “nX = new namespace()” call will indeed create a new set of objects clustered ‘under’ the namespace. So nothing will be shared between n1 and n2, in that case.
My aim was to show an important javascript idiom, which has to be used in any sizeable javascript app.
Here I think we see javascript being “easy” still requires a lot of discipline in its actual use.
Regards: Dusan
I have no doubts that you understand what you are doing, but try this:
This shows that each call of the
namespace()
1) creates its own copy of inner object(this.O) and 2) creates its own copy of thecounter
variable.But each call of the
namespace()
returns the same instance of global namespace object - in browser context it is known as 'self' or 'window' (bad name, imo).()
There are several ways to skin this javascript cat, too ;o) And to make things even less exact it is largely a matter of taste. Technically all these “namespace” solutions work. For example, consider this:
Can it be simpler that this? Hardly. Is this “dirty” or “tricky” ? Maybe. But it still works equally well. Do you like it? Do I like it? Maybe, but does it matter? This is javascript: flexible and productive.
Greetings: Dusan
Yeah, but we’ve returned back to starting point.
Your
my_namespace.o1
is not protected. By writingmy_namespace.o1 = null;
you can silently ruin your namespace.You should have some way to establish controllable perimeter on it. And original
envelope
does just that.If that matters, in tiscript I have added ‘type’ keyword that allows to define such namespaces like:
So you can access it as:
But these will generate errors:
‘type’ in tiscipt is an ordinary ‘object’ with all members read only by default.
To Steven: I think you did not get the point of this article.
Yes, you can write something like this:
and so to override/replace getFirst method for this object instance.
But there is no way in JS to get access to
m_first
andm_second
member variablesby other methods. Only
get/setFirst()
andget/setSecond()
functions can see and modify them. And that is the point of the article.