This post will focus on exploiting the similarities between functions and objects. Just as you can attach properties to objects, functions can also have properties attached.

   var myObj = {};
   var myFn = function() {};
   myObj.prop = "ship (cruise)";
   myFn.prop = "frigate (mission)";

Event callback management is one of several uses for this aspect of functions. In the following code sample by using the function’d id property fn.id we can add the frigate function to the shipyard object’s dock.

var shipyard = {
  pierId: 1,

  dock: {},

  add: function(fn) {
         if(!fn.id) {
            fn.id = shipyard.pierId++;
            return !!(shipyard.dock[fn.id] = fn); // the !! returns the Boolean value of any JavaScript expression
         }
    }

}

function frigate() {};
if(shipyard.add(frigate)){
  alert("frigate was added to shipyard");

 if(!shipyard.add(frigate)){
  alert("frigate was added once");
}
}

Memoization

This technique is used to store processor intensive calculated values. It makes your code much more efficient, especially when the same calculation is repeated several times. One common application is to store DOM elements by tag name.

function isPrimeNbr(val) {
   if(!isPrimeNbr.answers) isPrimeNbr = {};
if(isPrimeNbr.asnwers[val] != null) {
     return isPrimeNbr.answers[val];
     }
   var prime = val != 1;
for( var i = 2; i < val; i++) {
    if (val % i == 0) {
    prime = false;
    break
}
}
return isPrimeNbr.answers[val] = prime;
}
if(isPrimeNbr(57){
  alert("57 is a prime number");
}
if(isPrimeNbr.answers[57]){
 alert("The answer was safely cached");
}

The code below shows an example of memoizing DOM elements by tag name. The downside of this is memory that gets tied down, the improved performance compensates for this. Also some may argue that caching should not be performed by functions meant for business logic in order to keep separation of tasks intact.

function getElements(name){
   if (!getElements.cache) getElements.cache = {}
return getElements.cache[name] = getElements.cache[name] || document.getElementByTagName(name);
}

Array methods

Javascript Arrays are also Objects and this commonality can be used to create some interesting techniques. In situations where an Object contains a collection of data and also needs to store certain metadata concerning the data collection. Simply creating a new Object each time we need different metadata properties would be inefficient and time consuming. The example below shows how you can create an Object and then apply existing Array methods to it.

<body>
<input id="ying" />
<input id="yang" />
<script type="text/javascript">
var elems = {
    length:0,

    add: function(elem) {
         Array.prototype.push.call(this, elem);
    },

    gather: function(id) {
    this.add(document.getElementById(id));
    }
};

elems.gather("ying");
if(elems.length == 1 && elems[0].nodeType){
  alert("Verify that there's an element in our store");
}

elems.gather("yang");
if(elems.length == 2 && elems[0].nodeType){
  alert("Verified that Ying has got a Yang");
}
</script>

</body>

The code sample above shows a conventional object elems that has been set up to behave like an array. First it has a length property. It also has a method add() that inserts new elements, this method is implemented using Array.prototype.push. Normally, the context of Array.prototype.push is the array itself, however in this case by using the call() method the context is defined as the elems object. By so doing the length property is also incremented as in a regular array. The gather() method is more of a helper function that retrieves the DOM elements by id and invokes the add() method to insert the elements into storage.