AntonSack
AntonSack

Reputation: 1051

Javascript singleton: How to access private variables?

I have this singleton. The public functions allow to set private variables but I am not able to set them in the way that I am able to use them in the private methods:

var ServiceInterface = (function () {
  // Instance stores a reference to the Singleton
  var instance;

  function init() {
    // Singleton
    // Private methods and variables
    var m_action;

    function performAction() {
      alert(m_action);
    }

    return {
      // Public methods and variables
      callBackend: function (sAction) {
        m_action = sAction;
      }
    };
  };
})

m_action is not available throughout the public and private section of the singleton. What am I doing wrong?

Upvotes: 3

Views: 1309

Answers (2)

Reactgular
Reactgular

Reputation: 54781

This is how you create a singleton with a private member variable.

ServiceInterface = new (function() {
    var m_action = false;

    this.setAction = function(s) {
        m_action = s;
    };
    this.getAction = function() {
        return m_action;
    };

    this.performAction = function() {
        alert(ServiceInterface.getAction());
    };

    this.createCallback = function() {
        return function(sAction) {
            ServiceInterface.setAction(sAction);
        };
    }
})();
ServiceInterface.setAction("secret");
ServiceInterface.performAction();

ServiceInterface becomes a singleton because the constructor function is thrown away after it's created. ServiceInterface = new (.....)(); is how it's executed right after being declared. It's a singleton because there is no way for someone to create another instance.

I don't use var to create the instance. When you exclude var and you're not inside a function the new variable will be attached to the prototype of the parent object. In the browser this will be window. window is like a global singleton in javascript.

The local variable m_action is persisted because setAction and getAction reference it as closure functions, and the variable is attached to their scope. So they can be used as setter/getter methods.

You can now use ServiceInterface.setAction(sAction); in your callbacks to set the private member.

http://jsfiddle.net/thinkingmedia/w7DdE/6/

Upvotes: 1

OnesimusUnbound
OnesimusUnbound

Reputation: 2946

I think you're referring to this

var ServiceInterface = (function () {
    var m_action;

    function performAction() {
      alert(m_action);
    }

    return {
      // Public methods and variables
      callBackend: function (sAction) {
        m_action = sAction;
        performAction();
      }
    };
})()

ServiceInterface.callBackend("Hello world");

You need to execute anonymous function. Running it enables to create variables and functions defined with the anonymous function and these cannot be seen outside. Most of js libraries use this convention to create modules and to avoid infecting the global scope

var ServiceInterface = (function () {
   // code inside 
})()

These are the variables and functions confined within the scope of anonymous function executed

// var ServiceInterface = (function () {
    var m_action;

    function performAction() {
      alert(m_action);
    }

// })()

Finally, return a javascript object that will expose functions that can be accessible outside the anonymous function scope

//var ServiceInterface = (function () {
//  var m_action;
//    
//  function performAction() {
//       alert(m_action);
//  }

    return {
      // Public methods and variables
      callBackend: function (sAction) {
        m_action = sAction;
        performAction();
      }
    };
//})()

However, why go through the trouble of making private variable and method for a singleton?

Upvotes: 2

Related Questions