1

Assuming this code javascript code

(function(){ NameSpace = new function(){} //global namespace NameSpace.Apple = function(p_color){ var AppleInstance = this; //clarity.. AppleInstance.color = p_color; return { /************** / Public method /**************/ //Here, we only return an access to the Method Eat Eat : NameSpace.Apple.prototype.Eat } } //Will be public NameSpace.Apple.prototype.Eat = function(){ var AppleInstance = this; //clarity.. console.log("I'm eating a " + AppleInstance.color + " apple !") } //Will be private NameSpace.Apple.prototype.PrivateMethod = function(){ var AppleInstance = this; //clarity.. console.log("This is a private method"); } })() new NameSpace.Apple("blue").Eat(); //I'm eating a undefined apple ! 

As you can see, I have a class in a Namespace that contains 1 private variable, 1 private method and 1 public method. BUT when accessing to my public method, this one don't have access to the variable of the class.

I know that this is because of the :

return { /*...*/ } 

But is there a way that my public prototype method will access to my private variable (in my original code I want a Constant..) without giving access to it with the return.

If i return the properties in the return, the prototype methods will have access to it but not otherwise.

Thanks.

2
  • new function(){} - WTH? Commented Jun 20, 2013 at 18:48
  • What exactly do you think is your private variable? Also, your method is not really private. I can simply access (and even change) it via NameSpace.Apple.prototype.PrivateMethod Commented Jun 20, 2013 at 18:51

2 Answers 2

3

Nope. The two strategies are somewhat incompatible. Which is why private properties are usually public, but prefixed with an underscore, when using prototypes.

Namespace.Apple = function(p_color){ this._color = p_color; }; Namespace.Apple.prototype.eat = function(){ console.log("I'm eating a " + this._color + " apple !") }; 

This tells JS developers using this code that they should not mess with the _color property, as it's for internal use.


That said, you have other big problems here...

Namespace.Apple = function(p_color){ var AppleInstance = this; //clarity.. AppleInstance.color = p_color; return { /************** / Public method /**************/ //Here, we only return an access to the Method Eat Eat : NameSpace.Apple.prototype.Eat } } 

This doesn't do what you think. When a constructor returns an object, the instance created with new is discarded. So you will not end up with an instance of Apple. Instead you get a plain object that looks like this:

{ Eat: Namespace.Apple.prototype.Eat } 

So the object you assigned a color to? It's gone.


This method is not private.

//Will NOT be private Namespace.Apple.prototype.PrivateMethod = function(){ var AppleInstance = this; //clarity.. console.log("This is a private method"); } 

Everything on the prototype is public. Everything.


And a note about conventions.

var AppleInstance = this; //clarity.. 

I don't think is clear at all. this is used in instance methods to mean this instance. Any obfuscation of that hurts readability.

And please, save capital letter variable names for constructors (Eat bad!, Apple good!, AppleInstance bad!), also for readability. As calling a constructor without the new keyword can have some bizarre consequences.


To avoid this, and still have private variables and methods, you don't use the prototype at all. You set up all variables and methods as functions from within the constructor, building the instance piece by piece.

var Namespace = {}; Namespace.Apple = function(color){ // color form the arguments is a local variable, bound to the methods created below var somePrivateVar = 'privateData!'; // private instance variable // public method, with access to private instance vars this.eat = function(){ console.log("I'm eating a " + color + " apple!"); }; // public method, which calls private method this.doSomethingPrivate = function() { console.log('calling private method for you'); privateMethod() } // private method var privateMethod = function(){ console.log("This is a private method for a " + color + " apple!"); }; // instance is auto-returned, no return needed. } var apple = new Namespace.Apple('red'); apple.eat(); // I'm eating a red apple! apple.doSomethingPrivate(); // calling private method for you // This is a private method for a red apple! apple.privateMethod() // <exception> apple.privateMethod is undefined 

Only thing to note about this approach is that it can be much slower, and use more memory, than when you use prototypes. Functions on the prototype are shared between all instances, so you only need to create and store a single function for a method, and every instance will execute that function object.

With the above approach every single instance creates and stores a new copy of each method function. And each function has privileged access to the scope of that instances constructor, allowing you private variables and methods. If you only plan on having a few instances, this difference may not make a lot of difference. But if you plan on have a very large number of instances, the performance difference may become very important.

Sign up to request clarification or add additional context in comments.

2 Comments

Do not use _ (underbar) as the first character of a name. It is sometimes used to indicate privacy, but it does not actually provide privacy. If privacy is important, use the forms that provide private members. Avoid conventions that demonstrate a lack of competence. javascript.crockford.com/code.html
@Tareck117 Of course. It it's private for the sake of exposing a clean API underscore your property names. It it's private for security reasons, that is obviously a bad idea.
0

To achieve the encapsulation you're after the following structure would be advised:

(function(){ NameSpace = new function(){} //global namespace NameSpace.Apple = function(p_color){ var AppleInstance = this; //clarity.. var color; AppleInstance.color = p_color; this.Eat = function(){ /************** / Public method /**************/ //Here, we only return an access to the Method Eat alert("I'm eating a " + AppleInstance.color + " apple !") } //Will be private var private = function(){ var AppleInstance = this; //clarity.. alert("This is a private method"); } function constructor(p_color){ AppleInstance.color = p_color; } constructor(p_color) } })() new NameSpace.Apple("blue").Eat(); //I'm eating a blue apple ! new NameSpace.Apple("blue").private(); // Exception raised 

I'm never in favor of disregarding the this variable for a local copy, it has important implications for scope within the calling structure of JS objcects and gives a clue to developers as to where these might have changed.

As an aside: Namespace.Apple.prototype.PrivateMethod will not be a private method as everything exposed through a prototype is public.

1 Comment

Thanks. So if I understand, it's impossible to use prototype with private function because they will never be private ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.