After reading a bit on Javascript’s prototypical inheritance model, I change my style of constructing a class from
var Some_Class = function() {
this.public_method = function() {
};
(function() {
// constructor
}).call(this)
}
to
var Some_Class = function() {
(function() {
// constructor
}).call(this)
}
Some_Class.prototype.public_method = function() {
};
Although I understand that this is a good practice, but I am not allowed to access private methods from the public method anymore
var Some_Class = function() {
var private_member = 'whatever';
(function() {
// constructor
}).call(this)
}
Some_Class.prototype.public_method = function() {
return private_member; // not possible
};
After reading through an article here (Closure-created constructor), then I came out with this
var Some_Class = function() {
var private_member = 'whatever',
private_method = function(_some_value) {
// private method implementation
};
if(!arguments.callee.prototype.public_method) {
arguments.callee.prototype.public_method = function() {
private_method.call(this, private_method);
};
}
(function() {
// constructor
}).call(this)
}
However, what are the drawbacks of doing this?! or is there a better way of doing this if I want to access private member in the public method?
The use of function scope variables and closures to simulate private variables/functions is a well established idiom in the javascript community. If the variable is truly intended to be private, I see no drawback to this approach (although some claim that performant code on certain browsers/hosts has to pay attention to how many closures get created).
In your example, the private_method (and its environment) is shared across all objects – since your public_method closure is created only the first time the object is constructed (and bound to the constructor’s prototype property that sets the created object’s internal prototype chain) – so the private_method that is used is only the one that was created the first time.
Here is some sample code that will help illustrate what is going on:
var global = 1; var Some_Class = function() { var private_method = 'whatever'; var now = ++global; print("outer now: " + now ); private_method = function(_some_value) { // private method implementation print("inner now: " + now); }; if(!arguments.callee.prototype.public_method) { arguments.callee.prototype.public_method = function() { private_method.call(this, private_method); }; } (function() { // constructor }).call(this) } new Some_Class().public_method(); // outer now: 2, inner now: 2 new Some_Class().public_method(); // outer now: 3, inner now: 2 new Some_Class().public_method(); // outer now: 4, inner now: 2Are you sure that is what you want?
If your private_method does not need to refer to the enclosing object’s state, then I see little benefit in doing things the way you are doing.
What I usually do (if i have to use ‘new’ to create my object) is the following:
function MyClass() { var private_var = 1; function private_func() { } this.public_func = function() { // do something private_func(); } this.public_var = 10; } var myObj = new MyClass();The downside to this approach is that each time you construct the object via ‘new’ you re-create all the closures. But unless my profiler tells me that this design choice needs to be optimized, i prefer its simplicity and clarity.
Also I don’t see the benefit in your code of doing the following either:
(function() { }).call(this); // call the constructorWhy are you creating a separate scope in your constructor?