Thursday, November 11, 2010

JavaScipt Template Objects or Object Cloning

After doing a lot of research, I stumbled upon a talk by Nicholas C. Zakas  about Scalable Javascript Architecture.  Great!  Time to learn.


So, Yahoo has developed their own way of doing things.  They have created a 'Module' pattern.  If you watch the talk, he explains it in more detail.  The main idea is that the architecture is, ...well, MODULAR!  The problem is that he explains about the pattern without explaining all the parts that make it possible.


Let's start with creating an object that has 'Public' and 'Private' members and variables.  You start with making an object:


   var MyObj = function () {
                  var _myVar1;
                  var _myVar2;
  }

This will give your object private variables that are visible to any instance of the object, but not publicly visible.

Next, we add the functions that we want to the object:

MyObj.prototype = (function() {
              function func1 () {

              }


              function func2 () {

              }

              return {
                    // DON'T forget the constructor!
                    constructor: MyObj,
                    SomeFunctionName: func2
             }

})();

So, the key is that in the 'return' block, we add the functions we want to make public.  We can give whatever name we want to give, and that is the name with which we can access the function.  For instance,

        var myNewObj = new MyObj();
        myNewObj.SomeFunctionName();  // Will execute func2

We cannot access 'func1'.  It is private.


Next, we can look at trying to decouple objects from one another.  A main point of the talk was to stress the importance of knowledge of the layers.

The architecture looked something like:

                          MODULES
                          SANDBOX
                          APPLICATION CORE
                          LIBRARY


The modules should only know that the 'sandbox' exists, and have no knowledge of any other part of the system.

That's great and all, but how do we decouple the Application Core from the modules?

YUI has a built-in 'Clone' function.  Yay! Except, I don't want to have to incorporate YUI into my project just to use the clone feature.  I happen to use jQuery.

It took me a while to figure out, but I got it with some help from:  http://oranlooney.com/functional-javascript/

So, the reason we want to do this is, we want to be able to create module instances inside the AppCore, without the AppCore knowing about the modules directly.  We 'register' the modules with the AppCore and use a 'Start' method to start the module from the AppCore.

We don't want the AppCore creating direct instances of these modules.  So, the war around that is 'cloning'.

So, we have an object:


        var original = function () {
 
            var _name;
        
        }
 
        original.prototype = (function () {
 
            function Get() {
                return this._name;
            }
 
            function Set(name) {
                this._name = name;
            }
 
            return {
                constructor: original,
                Get: Get,
                Set: Set
            }
        })();


Now we want to use this object to create instances as modules in our system.  We don't want to directly create them, so we must do:


            var obj = new original();
 
            function Clone() { }
            Clone.prototype = obj;
 
            var test1 = new Clone();
            test1.Set("Locke");
            alert(test1.Get());
 
            var test2 = new Clone();
            test2.Set("Shepard");
            alert(test2.Get());
            alert(test1.Get());


This creates two instances of the original, without direct knowledge of it.

NOTE:  In the original object, you MUST use the pre-fix this, otherwise, if the private variable '_name' is changed, it is changed for all instances.  So, any reference to a variable inside that object that you do not want STATIC, you must have 'this.myVar'.  If you want it static throughout all instances, use 'myVar'.

No comments:

Post a Comment