12

Is there a way to call "public" javascript functions from "private" ones within a class?

Check out the class below:

function Class()
{
    this.publicMethod = function()
    {
        alert("hello");
    }

    privateMethod = function()
    {
        publicMethod();
    }

    this.test = function()
    {
        privateMethod();
    }
}

Here is the code I run:

var class = new Class();
class.test();

Firebug gives this error:

publicMethod is not defined: [Break on this error] publicMethod();

Is there some other way to call publicMethod() within privateMethod() without accessing the global class variable [i.e. class.publicMethod()]?

2
  • 4
    I hope it's just a typo in your example here, but your privateMethod is a global variable. Commented Apr 24, 2010 at 7:34
  • In Firefox if I call class.privateMethod() there is an error whereas class.publicMethod() works fine, so it seems like there is some difference between the two functions. Commented Apr 24, 2010 at 7:56

4 Answers 4

8

You can save off a variable in the scope of the constructor to hold a reference to this.

Please Note: In your example, you left out var before privateMethod = function() making that privateMethod global. I have updated the solution here:

function Class()
{
  // store this for later.
  var self = this;
  this.publicMethod = function()
  {
    alert("hello");
  }

  var privateMethod = function()
  {
    // call the method on the version we saved in the constructor
    self.publicMethod();
  }

  this.test = function()
  {
    privateMethod();
  }
}
Sign up to request clarification or add additional context in comments.

Comments

5

The accepted answer has the possibly undesirable side effect that separate copies of publicMethod, test, and privateMethod will be created in each instance. The idiom for avoiding this is:

function Class()
{}

Class.prototype=(function()
{
    var privateMethod = function(self)
    {
        self.publicMethod();
    }


    return 
    {
        publicMethod: function()
        {
            alert("hello");
        },
        test: function()
        {
            privateMethod(this);
        }
    };
}());

In other words, you need to pass the this to the private function as an argument. In return, you get a true prototype without having to pollute each instance with its own versions of the private and public functions.

1 Comment

Nice! Rather than pass in, you could always privateMethod.call(this) too
2

torazaburo's answer is the best one, as it avoids creation of multiple copies of the private members. I'm surprised that Crockford doesn't mention it at all. Alternately, depending on the syntax you prefer for declaring public member functions, you could do this:

function Class()
{}

(function() {
    var privateMethod = function(self) {
        self.publicMethod();
    };

    Class.prototype.publicMethod = function() {
        alert('hello');
    };

    Class.prototype.test = function() {
        privateMethod(this);
    };
}());

Comments

0

Is this approach not a advisable one? I am not sure though

var klass = function(){
  var privateMethod = function(){
    this.publicMethod1();
  }.bind(this);

  this.publicMethod1 = function(){
    console.log("public method called through private method");
  }

  this.publicMethod2 = function(){
    privateMethod();
  }
}

var klassObj = new klass();
klassObj.publicMethod2();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.