Polymorphism with JavaScript


I don’t know if I picked this line up in a book or somewhere else, but the best way to describe the JavaScript language is schizophrenic.  The language itself (regardless of the hosting environment) doesn’t know if it’s Object Oriented or Functional.  It’s always been my opinion that the functional aspects of the language are more powerful than the OO features, yet the least used.  This is probably my most classically trained OOP developers don’t really like JavaScript. The other reason is because most classically trained OOP developers coming from .Net and Java ( myself included) also forget that JavaScript is also a dynamic language.  So we try to get the language do things statically as we would expect other “grown up” languages to do.

This is why a lot JavaScript libraries try to add additional layers on top of the language to make it feel more like a static language.   Polymorphism is one of those features we expect from an Object Oriented language, yet the language itself doesn’t directly support this the way we expect it to (there are workarounds, but I’m not going into those).  But when you remember that JavaScript is dynamic, it become remarkably easy.

In our current project, we are using JQuery to make modifications to a legacy web application, where we REALLY don’t want to work on the server-side logic.  In this app we have two form that are exactly the same (for our purposes at least) except for one little detail.  On one page, a critical piece of information is in a drop down list, while on the other page, it just static html content.  So we need a little polymorphic behavior here, to retrieve this information differently.

To start with, we are using the Module Pattern to both contain our public methods in a single scope and to hide some of our methods from the public api.  So we exposed a method in our return object that we expect to override.

 

var module = function(){
 // private methods
 //return object that has our public methods
 return{
   getImportantField: function(){ alert("this method is not implement, write your own"}
 }
}();

 

On the page where we need to get this from the drop down list, we include these script files:

 

<script type="text/javascript" src="Module.js"></script>
<script type="text/javascript" src="GetImportantFieldFromDropDown.js"></script>

Now we can change the behavior of our method my replacing it at runtime.

module.getImportantField = function(){
    //access the field via the drop down
}

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, “Courier New”, courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }

And on the page where we need it from the text, we’ll include another file that changes the behavior of the method in question

<script type="text/javascript" src="Module.js"></script> 
<script type="text/javascript" src="GetImportantFieldFromDropDown.js"></script> 

</p>

.csharpcode, .csharpcode pre

{

font-size: small;

color: black;

font-family: consolas, “Courier New”, courier, monospace;

background-color: #ffffff;

/*white-space: pre;*/

}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt

{

background-color: #f4f4f4;

width: 100%;

margin: 0em;

}

.csharpcode .lnum { color: #606060; }

And of course change the behavior appropriately:

 

module.getImportantField = function(){
    //access the field via the html text
}

This approach takes advantage of the fact that browsers load source files in the order in which they are listed.  Also the fact that JavaScript treats methods like variables and you can replace their value at any time.  This opens up many new opportunities for structuring your code in dynamic languages that are not possible with static languages. Yes I know you can do similar things with delegates in C#, but you get my point.  I’m still learning what is possible with dynamic languages and utilize that to its fullest extent. 

Austin Code Camp 09 Call For Speakers