Javascript Private and Public Object Members

No Gravatar

Javascript can be a frustrating language to jump into. I can recall personal experiences from my early days with it when I was sure there was some voodoo involved. A big reason for my confusion is that I approached it like a classical object oriented language. You can spend time fighting it and trying to make it behave like Java but in the end you’ll have a more pleasant experience if you accept that programming in Javascript is a different paradigm than programming classical object oriented languages.

This article is going to focus on how to implement public, private and privileged object members. The article assumes you have a handle of the basic syntax of javascript and that you have classical object oriented programming experience.

Defining an Object

There are no classes in Javascript. So how do we define an object that we might want several instances of? With an object constructor:

var FormHelper = function () {
};
 
//now create an instance of the object.
var fh1 = new FormHelper();

That’s right, functions are objects in Javascript.

Public Object Members

Now let’s add a parameter and a public member to our object constructor. The parameter will be the id attribute of the form element we want help with. I’ll prefix the function parameter with p for clarity.

var FormHelper = function (pid) {
  this.id = pid;
};
 
var fh1 = new FormHelper("test-form");
 
alert(fh1.id);

The above alert will show you the contents of the public object member id.

Private Object Members

There are no keywords like private, protected or public in Javascript, instead you just need to be aware of Javascript’s quiddities. Defining the object member with “this” is what makes id public. “this” is a special variable which references the object whose scope you’re in, much like the “this” from Java and PHP. Now let’s make id a private object member.

var FormHelper = function (pid) {
  var id = pid;
};
 
var fh1 = new FormHelper("test-form");
 
alert(fh1.id);

Instead of adding id to “this” and making it public, we’ve defined it as a var. It’s now only accessible in the scope of our object. The alert line above will not display the id member of the FormHelper object, rather you’ll be shown undefined.

Public Object Functions

In Javascript a variable and a function encapsulated by an object are both considered object members. Let’s add a public function to our object to get the private member id.

var FormHelper = function (pid) {
 
  var id = pid;
 
  this.getFormId = function () {
    return id;
  };
 
};
 
var fh1 = new FormHelper("test-form");
 
alert(fh1.getFormId());

Note that when accessing private object members from a public object function we don’t specify “this”, however we do use “this” to access public object members. Since public functions can access private object members all public functions are considered privileged.

Private Object Functions

Now let’s change up the example a bit to illustrate a private function.

var FormHelper = function (pid) {
 
  var that = this;
  this.id = pid;  
 
  var getFormEl = function () {
    var id = that.id;
    return document.getElementById(id);
  };
 
  this.getForm = function () {
    return getFormEl();
  };
 
};
 
var fh1 = new FormHelper("test-form");
 
alert(fh1.getForm());

Something strange happens in private functions like getFormEl. The scope is not the same as public functions. In the context of private object functions “this” is set to the window object. To work around that we define a private object member “that” which is a reference to the encapsulating FormHelper object. There is nothing special about the variable “that”, we could have named it anything.

Summary

In an object constructor:

Define Public Private
Variable
this.varName = ...
var varName = ...
Function
this.functionName = function (...) {...};
var functionName = function (...) {...};

In object functions:

Access In Public Functions
In Private Functions
Public Variable
this.varName
that.varName
Private Variable
varName
varName
Public Function
this.functionName()
that.functionName()
Private Function
varName()
varName()

A Practical Example

We now have the tools to implement public and private object members, variables and functions inclusive. See if you can follow what’s happening in this more complete example. The Javascript makes use of YUI‘s type checking so if you were to try to execute the code below you’d need to include the following script tag in your html.

<script src="http://yui.yahooapis.com/combo?2.7.0/build/yahoo-dom-event/yahoo-dom-event.js" type="text/javascript"></script>

Imagine we have a form like so:

<form id="test-form" action="/some/script">
<label>Test Input</label>
<input name="test-input" type="text" value="default value" />
</form>

Here’s the javascript to help with the form.

/**
 * My own namespace so I'm not polluting the global namespace.
 */
CWS = {};
 
/**
 * An object constructor to demonstrate public, private and privileged
 * object members.
 */
CWS.FormHelper = function (id) {
 
  /**
   * We use the "that" variable in private functions where the "this"
   * variable is not what you might expect. The "that" and "formEl"
   * variables are private object members.
   */
  var that = this;
  var formEl = false;
 
  /**
   * This is a public object member. Note the use of the "this" variable.
   * That's what makes an object member public.
   */
  this.formId = id;
 
  /**
   * Set some initial values.
   *
   * A private object member.
   */
  var init = function () {
 
    /**
     * The "this" variable in the context of private object members
     * is the window object which is not what we want. The below
     * statement results in id being assigned with undefined since formId
     * was assigned to the FormHelper instance and not the window object.
     */
    var id = this.formId;
 
    /**
     * Luckily we were smart and created the "that" variable which is a
     * a reference to the FormHelper instance.
     */
    id = that.formId;
 
    if (YAHOO.lang.isString(id))
    {
      /**
       * This assigns the form element to the private variable formEl.
       */
      formEl = document.getElementById(id);
    }
 
    if (YAHOO.lang.isObject(formEl))
    {
      return true;
    }
    else
    {
      return false
    }
  }
 
  /**
   * Gets a form field element from a form.
   *
   * This is a private function.
   */
  var getField = function (name) {
 
    /**
     * Note that "formEl", a private object member is accessed from this
     * private function without the "this" variable.
     */
    for (var i = 0; i &lt; formEl.elements.length; i++)
    {
      var el = formEl.elements[i];
 
      if (el.name == name)
      {
        return el;
      }
    }
 
    return false;
  };
 
  /**
   * Gets the current value from a form field.
   *
   * This is a public function, and public functions can access private
   * object members.
   */
  this.getValue = function (name) {
 
    /**
     * Here we're calling a private function. Note that getField is not
     * prefixed by "this" or "that".
     */
    var el = getField(name);
 
    if (!el)
    {
      return false;
    }
 
    return el.value;
  };
 
  /**
   * This is not a great practice but gives us the opportunity to use the
   * "that" variable.
   */
  if (!init())
  {
    alert ("Failed to create a CWS.FormHelper instance.");
  }
};
 
var fh1 = new CWS.FormHelper ("test-form");
 
/**
 * Calling the below results in an error since the function is private.
 */
try
{
  var el = fh1.getField("test-form"); //error
}
catch (e)
{
  //alert("We tried to call a private object member!");
}
 
/**
 * The below assigns undefined to the global variable "formEl" it's trying
 * to access a private object member.
 */
var formEl = fh1.formEl;
 
if (!YAHOO.lang.isUndefined(formEl))
{
  alert ("This alert never happens.");
}
 
/**
 * We must use the privileged getValue function to get the data we want. Public
 * functions are privileged.
 */
var inputValue = fh1.getValue ("test-input");

One Response to “Javascript Private and Public Object Members”

  1. Tim LongestNo Gravatar says:

    Hey, I found this blog post while searching for help with JavaScript. I have recently switched browsers from Chrome to Microsoft Internet Explorer 5. After the change I seem to have a problem with loading JavaScript. Every time I browse site that needs Javascript, the site doesn’t load and I get a “runtime error javascript.JSException: Unknown name”. I cannot seem to find out how to fix it. Any aid is greatly appreciated! Thanks

Leave a Reply