1

I recently learned a little more about nesting functions and discovered that I'm writing inefficient code by defining methods right inside a constructor: this.method=function(){} and read that it would be more efficient to use: constructor.prototype.method=function(){}. However, Before I was writing 'private' properties as local variables and defining getters within the constructor:

function class(prop)
{
   var prop2=prop*2;
   this.__defineGetter__('prop2',function() {return prop2;});
}

But I quickly realized that removing the second line in the constructor and using class.prototype.__defineGetter__('prop2',function() {return prop2;}); returns a blank string

Is there maybe a way to fix this? or an altogether better way to make properties in an object only accessable by abstraction?

Jim Jones
  • 2,568
  • 6
  • 26
  • 43
  • Best not to use instance specific "private" variables. You can indicate that they're private by their name `_myprivate` would show other programmers and your future self that you should not access them directly. You can't have methods on the prototype and access instance specific private variables, you can have shared private members on the prototype, some patters and more detail can be found here: http://stackoverflow.com/a/16063711/1641941 – HMR Dec 22 '13 at 09:33
  • Slightly off topic, but does anyone know if ecmaScript 6 includes anything for this in its new class specification? – Jim Jones Dec 22 '13 at 09:46

2 Answers2

1

If you want to have private variables like prop2, then you have to define the methods that access them within the scope of the private variables (which is inside the constructor), thus you can't use the prototype for those methods.

Simple tradeoff - you have to pick one or the other.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Darn, thanks though, would you say that performance loss in defining getters in the constructor is substansional? – Jim Jones Dec 22 '13 at 09:06
  • Unless you're creating thousands of these objects in a loop, I doubt you would notice the difference. You can always create a performance test in something like jsPerf to measure the difference. – jfriend00 Dec 22 '13 at 09:21
  • @SpencerKillen Having your functions in the constructor body makes it harder to re use then when inheriting `Parent.prototype.someMethod.call(this,arg1,arg2);` is not possible and you'll have to come up with a more complicated solution. About performance: you may not notice the difference but someone having your site in a tab with 10 other tabs on a low end Android phone might. The fact remains: your code will use more cpu and more memory. But if you have a really good reason to have private members then go for it. – HMR Dec 22 '13 at 09:40
1

Private properties in JavaScript rely on the closure mechanism to preserve the lexical scope (or, said plainly, the available variables) at the time a function/getter is defined. In other words, no, you can't do it outside of the constructor if you want the properties to remain private. Trying to do this anywhere else is going to either "leak" access or is not going to be a part of the prototype.

The reason that your example works is because the getter closes over (and therefore retains access to) prop2 even after the constructor has returned.

Wayne
  • 59,728
  • 15
  • 131
  • 126
  • 1
    Thanks @lwburk , I was actually quite curious as to why the prop wasn't destroyed at that end of the constructor, Is this actually considered 'good practice' or should I try an avoid it? – Jim Jones Dec 22 '13 at 09:04
  • @SpencerKillen - closures are a very useful construct in javascript and there is no reason to avoid them if needed. If you want a truly private variable, then a closure is the only way to implement it. – jfriend00 Dec 22 '13 at 09:22