Web: Polymorphic JavaScript Functions

by Stephen Chapman

One aspect that not many people ever think about with JavaScript is that if you define multiple functions with the same name then the last one defined will be the one that actually runs. JavaScript functions are not polymorphic the way that functions in many other languages are in that JavaScript doesn't care if the actual arguments defined for the functions are different as it can't distinguish between them on that basis. Where in other languages you might have myfunc(oneparm) and myfunc(parmone, parmtwo) as two separate functions with the one that gets run depending on the number of parameters passed, in JavaScript the last one defined will always be the one run regardless of the number of parameters.
The only time most people will ever even think about this aspect of how JavaScript works is when they accidentally create two functions of the same name (perhaps by incorprating two different scripts into the same page) and then wondering why their code doesn't work properly.
Instead of being a failing in the JavaScript language though, this way of handling duplicated function names actually provides us with a way to make JavaScript even more polymorphic with its function processing. To start with, it is relatively simple to recode our multiple functions so that they will behave polymorphically, we just need to give each a separate nale and then set up one extra function that will be the one that we call which itself examines the number and types of the parameters passed in order to decide which of those other functions to call.
Doing that is not as efficient in terms of the required code as languages that do that selection automatically are but it does make available to us a way to make our JavaScript functions even more polymorphic than is possible in other languages. Instead of the parameters passed to the function being polymorphic we can set things up in JavaScript so that the function itself is polymorphic and changes itself.
A good example of this was included in the presentation given by Dan Webb at the @media Ajax 2007 conference. In his presentation he used the following example.
function addEvent(obj,evt,fn) {
  if (document.addEventListener) {
    addEvent = function (obj,evt,fn) {
  else if (document.attachEvent) {
    addEvent = function (obj,evt,fn) {
This function effectively rewrites itself the first time it is called by creating another function having the same name as the original function. As this new function has been added to the page after the original function, it will be the one that is used for all subsequent calls to that function name but because the second function by that name has not yet been added to the page the first time the function is called, te original function (the one that recreates itself) will be the one called the first time that the function is called.
This allows us to dramatically reduce the feature sensing code that we would otherwise need in our scripts in order to determine what code we need to run based on the features supported.
This particular example uses feature sensing to add event processing to the web page. If the browser is running JavaScript that supports addEventListener() then the addEvent() function will replace itself with a function that calls addEventListener. If the browser is running JScript which supports attachEvent() then the function will replace itself with a function that calls attachEvent. In effect there are three different addEvent() functions in our web page. The first is called the first time the function is called. That function works out which of the two features that the browser supports and replaces itself with a function that uses that feature to do the processing. It then calls that replacement function in order to perform that task. Subsequent calls to the function will reference the added function directly as it has been added to the page after the original function. Since this function does not perform the feature sensing it will run more efficiently. As it is impossible for a browser to suddenly stop supporting one feature and start supporting another in the middle of processing a script we do not need to perform feature sensing tests more than once in processing the page and so a polymorphic function like this is way more efficient than the more conventional approach of testing the feature every time would be.

No comments:

Post a Comment