Practical ASP.NET

JavaScript for the ASP.NET Developer: Learning To Function

Peter continues to explore the differences between the .NET object-oriented, server-side languages he's used to and the world of JavaScript.

In my last column, "JavaScript for an ASP.NET Developer," I described the culture shock I experienced at discovering that JavaScript isn't an object-oriented language. As a result, I finally started dealing with JavaScript on its own merits rather than expecting it to work like the languages I was used to. And, as I said in that column, one of the beneficial results of that mental adjustment has been a grudging (but growing) respect for the language.

Defining Functions
For instance, I've become very fond of the way that JavaScript deals with executable code (functions), though JavaScript's unique features can be hidden by the syntax. For instance, I can define a function in JavaScript with code like this:

function ReturnTrue() 	
{
  return true;
}; 

For an old programmer like me, this code looks very familiar. However, this syntax disguises what JavaScript is actually doing. The alternative syntax is more expressive of what's going on in JavaScript:

var ReturnTrue = function() 	
{
  return true;
};

As this syntax applies, what's happening here is that a variable (called ReturnTrue) is being set to a function. With that reference made, I can now call that function through the variable:

var result;
result = ReturnTrue();

I'm not defining a function named "ReturnTrue" -- I'm defining a function which can be called through the variable "ReturnTrue." To call the function, I must add parentheses at the end of the variable name; parentheses are the "invocation operator."

If, on the other hand, I omit the invocation operator (the parentheses), then I'm simply assigning the value of one variable to another variable. This example results in a second variable (called ReturnTrue2) holding a reference to the function:

var ReturnTrue2;
ReturnTrue2 = ReturnTrue; 

Now that the ReturnTrue2 variable is referencing the function, I can call the function through the second variable:

var result;
result = ReturnTrue2();

I'm not totally happy, of course. It's too bad that the difference between assigning a function to another variable and invoking the function is so small. A good rule to follow in user interface design is, "Small differences should require small changes; large differences should require large changes." In my mind, the difference between returning a result and assigning a reference is a large one and should be signaled by more than just the presence or absence of a set of parentheses. For me, a different kind of assignment operator would have been a better choice when moving a reference around (I'm probably still hanging onto the old Visual Basic 6 "Set" keyword). But it's too late to complain now.

Adding Functions to Objects
What I do like is that this ability to store a reference to a function in a variable provides an elegant way to add methods to data structures. This example extends my data structure from the last column just by setting one of the structure's elements to a function that returns a date a year in the future:

var salesOrder =
 {
   id: "",
   dateOrdered: new Date(),
   cancelDate: function () 
    {
       var d = new Date(); 
       d.setYear(d.getYear() + 1); 
       return  d.toLocaleString();
    }
 };

As with any structure, I can use salesOrder immediately. This example calls the cancelDate function:

var dateForCancellation = salesOrder.cancelDate();

Using a term familiar to C# programmers ("this") allows me to reference other elements in the same structure from within my function. This version of my structure lets me use the dateOrdered element in my structure as part of the code in my function:

var salesOrder =
{
  id: "",
  dateOrdered: new Date(),
  cancelDate: function () 
   {
     var d = this.dateOrdered; 
     d.setYear(d.getYear+1); 
     return  d.toLocaleString();
   }
};

As I said, I have to admit that I like this feature very much. For instance, I can now add getters and setters to my structure to control what values are accepted into elements in the structure. This example adds a getter (setArrivalDate) that ensures the value put into arrivalDate is later than today's date:

var salesOrder =
     {
       arrivalDate: new Date(),
       setArrivalDate: function(proposedArrival)
      {
        var todayDate = new Date();
        if (proposedArrival > todayDate)
        {
          this.arrivalDate = proposedArrival;
        }
     },
     ...

So, the learning is ongoing. I'm almost ready to start using constructors in JavaScript...

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

Subscribe on YouTube