1

I have an existing class I need to convert so I can append functions like my_class.prototype.my_funcs.afucntion = function(){ alert(private_var);} after the main object definition. What's the best/easiest method for converting an existing class to use this method? Currently I have a JavaScript object constructed like this:

var my_class = function (){

 var private_var = '';
 var private_int = 0
 var private_var2 = '';
 [...]

 var private_func1 = function(id) {
  return document.getElementById(id);
 };

 var private_func2 = function(id) {
  alert(id);
 };

 return{
  public_func1: function(){

  },

  my_funcs: {
   do_this: function{

   },
   do_that: function(){

   }
  }
 }
}();

Unfortunately, currently, I need to dynamically add functions and methods to this object with PHP based on user selected settings, there could be no functions added or 50. This is making adding features very complicated because to add a my_class.my_funcs.afunction(); function, I have to add a PHP call inside the JS file so it can access the private variables, and it just makes everything so messy.

I want to be able to use the prototype method so I can clean out all of the PHP calls inside the main JS file.

Aaron Butacov
  • 32,415
  • 8
  • 47
  • 61
  • Just to clarify, the most important part is accessing private variables from appended functions. Using "prototype" is unnecessary as long as **my_class.my_funcs.afunction();** is appended to the object outside the main class and can access private_var. – Aaron Butacov Oct 26 '10 at 20:30
  • What you have is an object, not a class. More precisely it is a singleton. If you were using constructor calls to create new objects based on your function, then we could call it a "pseudo-class". But, this is not the case here. – Šime Vidas Oct 26 '10 at 20:46
  • I am not sure that I understand you correctly. Are you saying that just augmenting the `my_class` object is not an option for you? (Like: `my_class.my_funcs.afunction = function() { ... };`) – Šime Vidas Oct 26 '10 at 20:51
  • Augmenting it in such a way that the private variables of my_class can be accessed is the issue. Everything else is easy. – Aaron Butacov Oct 26 '10 at 20:54
  • I believe that once you create the `my_class` object, you **cannot** add new methods to that object which would be able to access the private members directly. Once the `my_class` object is created, the scope inside which the private members exist has ended and the only reference to that scope exists from within the functions that were returned (`public_func1`, `do_this` and `do_that`) – Šime Vidas Oct 26 '10 at 21:55

3 Answers3

0

Try declaring your "Class" like this:

var MyClass = function () {
    // Private variables and functions
    var privateVar = '',
        privateNum = 0,
        privateVar2 = '',
        privateFn = function (arg) {
            return arg + privateNum;
        };
    // Public variables and functions
    this.publicVar = '';
    this.publicNum = 0;
    this.publicVar2 = '';
    this.publicFn = function () {
        return 'foo';
    };
    this.publicObject = {
        'property': 'value',
        'fn': function () {
            return 'bar';
        }
    };
};

You can augment this object by adding properties to its prototype (but they won't be accessible unless you create an instance of this class)

MyClass.prototype.aFunction = function (arg1, arg2) {
    return arg1 + arg2 + this.publicNum;
    // Has access to public members of the current instance
};

Helpful?

Edit: Make sure you create an instance of MyClass or nothing will work properly.

// Correct
var instance = new MyClass();
instance.publicFn(); //-> 'foo'
// Incorrect
MyClass.publicFn(); //-> TypeError
xj9
  • 3,381
  • 2
  • 24
  • 23
  • Is there any method that will allow MyClass.prototype.aFunction() to access privateNum like MyClass.publicObject.fn() can? – Aaron Butacov Oct 26 '10 at 20:19
  • @Aaron: No. You can only access private variables if they are in the same scope. – xj9 Oct 26 '10 at 23:13
0

Okay, so the way you're constructing a class is different than what I usually do, but I was able to get the below working:

var my_class = function() {
    var fn = function() {
        this.do_this = function() { alert("do this"); }
        this.do_that = function() { alert("do that"); }
    }
    return {
        public_func1: function() { alert("public func1"); },
        fn: fn,
        my_funcs: new fn()
    }
}
var instance    = new my_class();
instance.fn.prototype.do_something_else = function() { 
    alert("doing something else"); 
}
instance.my_funcs.do_something_else();

As to what's happening [Edited]:

  • I changed your my_funcs object to a private method 'fn'
  • I passed a reference to it to a similar name 'fn' in the return object instance so that you can prototype it.
  • I made my_funcs an instance of the private member fn so that it will be able to execute all of the fn methods

Hope it helps, - Kevin

Kevin Nelson
  • 7,613
  • 4
  • 31
  • 42
0

Maybe I'm missing what it is you're trying to do, but can't you just assign the prototype to the instance once you create it? So, first create your prototype object:

proto = function(){
    var proto_func = function() {
        return 'new proto func';
    };
    return {proto_func: proto_func};
}();

Then use it:

instance = new my_class();
instance.prototype = proto;
alert(instance.prototype.proto_func());
Hollister
  • 3,758
  • 2
  • 20
  • 22
  • I've updated the question, but accessing private variables is the part I'm getting stuck on. I've tried 3 or 4 different methods I could come up with and can't reliably use them. – Aaron Butacov Oct 26 '10 at 20:45
  • Ah. Then check this out: http://stackoverflow.com/questions/436120/javascript-accessing-private-member-variables-from-prototype-defined-functions – Hollister Oct 26 '10 at 20:55