The JavaScript Singleton Pattern Part II   Leave a comment





Aveune Of The America NYC July 4th, 2009
By dlr2008

The Singleton Saga – Part I
The Singleton Saga – Part II
The Singleton Sage – Part III

Closures are one of the most powerful features of ECMAScript (JavaScript) but they cannot be property exploited without understanding them. They are, however, relatively easy to create, even accidentally, and their creation has potentially harmful consequences, particularly in some relatively common web browser environments. To avoid accidentally encountering the drawbacks and to take advantage of the benefits they offer it is necessary to understand their mechanism. This depends heavily on the role of scope chains in identifier resolution and so on the resolution of property names on objects.

In comp.lang.javascript FAQ

Most of what we will discuss today is taken from Crockford’s seminal essay on Private Fields And Closure. Please note: The current examples (and those in Crockford’s essay) depend on the use of the JavaScript “new” verb in order to ‘instantiate’ a JavaScript object. Crockford’s more recent work treats “new” as unsafe JavaScript. As such, his JSLint program will flag uses of new with warnings in its ‘strict’ mode. I, personally, don’t have a problem with “new” in JavaScript but we will not go into that debate here. Part III will introduce a non-“new” constructor method anyway.So, let’s begin.

Recall how private methods (aka inner methods) can be defined in an object:

1. function Container(param){
2.    return makeSmall(param);
3.     function makeSmall(arg){
4.          return arg.toLowerCase();
5.     }
6.  }
7. var out=Container('BIGFISH');

Nothing fancy here. Let’s look at this short code segment as the un-threaded JavaScript inturprature
looks at it.

  • Read line #1. Create a object called “Container” enclosed by brackets at line #1 and line#6.
  • Read lines #1 through #6, check for syntax and DO NOT EXECUTE any code.
  • Create an enclosure within Container called “makeSmall”. Lines #3 through #5
  • Read line #7, check for syntax and EXECUTE Container(‘BIGFISH’);
  • Execute line #2. To do so:
    • Execute the function makeSmall on line #3
    • Return the results of makeSmall as the results of the call to Container

the var “now” then contains the string ‘bigfish’

“makeSmall” is an inner method of Container ( Often called a private function by Crockford). In addition

to methods we can create private fields within an object with syntax like this:

function Container(param){
            var privateField;
}

“privateField” is, like “makeSmall” in the prior example, not visible outside of Container.

Public Methods and Fields At Last: Using “new” in JavaScript

Ok, we are almost there. Here is something that looks

like a class definition (but its not really). The following code is NOT executable by itself.

function Container(param) {
     function makeSmall(arg){
          return arg.toLowerCase();
    }
    var member = param;
    this.Service = function () {//use of "this" is required here
            return member;
        }
     this.PublicField='Everyone Sees Me, I hope';//use of "this" is required here.
}

In this container we have defined two private objects:

  • the private function: makeSmall; and
  • the private field: member; and

we have defined two public objects:

  • a public function: this.Service
  • a public field: this.PublicField

To use “Container” object we need to deploy the “new” verb:

var b=new Container2('abc');
alert(b.Service()); //this will return the string 'abc';

Note that Service is public and is defined using JSON syntax: this.Service = function(){…};

Crockfords notes that, defined this way, Service can only reference private members,

and fields within the Container object. We can do better, but we must work a little harder.

What is all this THIS and THAT stuff anyway?

We might try to create a global field by the following (improper) syntax:

1. function Container(param) {
2.    PublicField=param;
3. }
var b=new Container3('wow');

We can test the results by doing the following:

line 4. var c=b.PublicField;
line 5. var d=PublicField;

Variable “c” is now equal to ‘undefined’ (the type, not the string); and
Variable “d” is now equal to ‘wow’;

What went wrong here? Line # 2 defines PublicField as a global (within the current execution context)

The variable PublicField is  not associated in any way with Container. Container.PublicField is Not defined so the

attempted reference to it, via b.PublicField returns undefined.

All of this is expected and legal behavior, its just not the behavior we want. It seems like what we

want is a syntax which users the “this” key word. But this way there be dragons. The this key word

will also be used to allow our public and private functions to access public fields. Here is the code

first (more or less straight from Crockford) and more discussion follows the code.

function Container(param) {
    function dec() {
        if (privateField < 0) {
            privateField -= 1;
            return true;
        } else {
            return false;
        }
    }
   this.PublicField=param.toLowerCase();
    var member = param;
    var privateField = 3;
    var that = this;
    this.Service = function () {
        if (dec()) {
            return member;
        } else {
            return null;
        }
    };
    this.SpecialService = function () {
        if (dec()) {
            return that.PublicField;
        } else {
            return null;
        }
    };
}

//Testing:
var myContainer=new Container('FATCAT');
//var myContainer is now an object of type Container
var b=(new Container('FATCAT')).Service();             
//var b now equals 'FATCAT'
var c=(new Container('FATCAT')).SpecialService()      ;
// var c now equals 'fatcat'
var d=(new Container('FATCAT')).privateField      ;         
//var d now equals type 'undefined'

In this code we have the following:

Object

Type

Access

Notes

dec

Function

Private

This.PublicField

Field

Public

privateField

Field

Private

Private
fields are static within the derived object (i.e. var x=new Container(…);)

Member

Field

Private

that

Field

Private

Pointer
to the execution context in the Container object was instantiated. This
private field must be used within any private or public function to access
Public Fields and Functions. Note, that “that” must be set during object instantiation
only.

this.Special

Function

Public

This
function accesses only private fields.

This.SpecialService

Function

Public

This function accesses private functions and fields. It also access a public Field (that.PublicField).

Container is a JavaScript object but it can ONLY be used
with a “new” statement:

var myContainer=new Container('FATCAT');

Container is NOT a class definition (no such animal exists in JavaScript). Here is the walk through of code execution during a instantiation.


  • The object “myContainer” is instantiated as an instance of Container.
  • Function dec is defined but not executed.

  • · This.PublicField is defined and set to the lower case of the input parameter.

  • · member is defined and set to the original value of the input parameter.

  • · privateField is defined and set to the value of 3.

  • · “that” is defined and set to “this”. At this execution moment, “this” is equal to a pointer to the execution context where the object “a” is being created. JavaScript does not guarantee that the value of “this” will remain constant during the course of your program execution.  Please see the PS at the end of this blog for additional information.

  • · this.Special is defined and not executed.

  • · this.SpecialService is defined and not executed.

Ok, so much for this, that and the other thing. In the next post on this subject we will find a syntax to allow us to do away with the “new” verb and still get an object back in return.

PS

One additonal word about using the parttern:

var that=this;

The stratagy of using “that” is required when you need to make internal references to Public properties of the object.

From the above example if we are given:

   this.PublicField=param.toLowerCase();
   var that=this;
    this.SpecialService = function () {
        if (dec()) {
            return that.PublicField;
        } else {
            return null;
        }
    };

the reference to PublicField in:

return that.PublicField;

Requires the use of the that modifier. However references to private (internal) properties explicitly

require NOT using the “that.” modifier.

In the current example note how the function “dec” is coded:

function dec() {
        if (privateField < 0) {
            privateField -= 1;
            return true;
        } else {
            return false;
        }
    }

Well, now you have been warned.

Good Bye, And Good Luck

dlr2008

The Singleton Saga – Part I
The Singleton Saga – Part II
The Singleton Sage – Part III

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: