Stuff about software development, agile and testing

Thursday, August 7, 2008

Understanding The Misunderstood, JavaScript Part 1

Many of us work with JavaScript in daily basis but only few actually consider JavaScript as a powerful programming language. But new renaissance of JavaScript frameworks prove that there is something about this language that we haven't learned yet. This mini part series of blog posts will give another shot at JavaScript.

So what went wrong?

JavaScript was developed by Brendan Eich at Netscape as the in-page scripting language and most often used for client-side web development. It is a remarkably expressive dynamic programming language. JavaScript, despite the name, is essentially unrelated to the Java programming language. This language was renamed from LiveScript in a co-marketing deal between Netscape and Sun in exchange for Netscape bundling Sun's Java runtime with their then dominant browser. I think this is the main contributor to the misunderstanding we had about this language.

Most programmers never realized the true power of this language. The reason being most of the people writing JavaScript in early days were not programmers and they lacked the training and discipline to write good programs hence finding good JavaScript materials or examples were hard. Along with those browser incompatibilities, bugging implementation gave an impression that this language is not ready for professional programming. This is simply not true anymore, in many ways we can say that suddenly the bar was put much higher in front of us as we started to see some smart JavaScript programs and applications. And as the web is becoming target platform for Web 2.0 applications, scripting languages and other dynamic languages are currently experiencing a renaissance. JavaScript is becoming the only scripting language of the web and its clearly becoming important to understand this language, its paradigms, and its semantics.

Re-introducing JavaScript

JavaScript is prototype based object oriented dynamic language descendant from Self. Quite a mouthful! right? Lets explore.

If you are familiar with prototype design pattern, you know that in this creational pattern objects are created from a prototypical instance. JavaScript uses the same concept to create new instances, by cloning existing objects that serves as prototype (more about this later). This is quite different from class based languages in which objects comes in two distinctive taste, classes as collection of behavior and instances as state holder.
In JavaScript, objects hold both the behavior and state. This language semantic enables the programmer to focus on behavior without worrying about the abstractions and relationships upfront. Here is nice comparison of prototype-based language with class-based language from wikipedia


Traditional class-based OO languages are based on a deep-rooted duality:
1. Classes define the basic qualities and behaviors of objects.
2. Object instances are particular manifestations of a class.

For example, suppose objects of the Vehicle class have a name and the ability to perform various actions, such as drive to work and deliver construction materials. Porsche 911 is a particular object (in-stance) of the class Vehicle, with the name "Porsche 911". In theory one can then send a message to Porsche 911, telling it to deliver construction materials.

This example shows one of the problems with this approach: Porsches are not able to carry and deliver construction materials (in any meaningful sense), but this is a capability that Vehicles are modeled to have. One way to create a more useful model is to use subclassing to create specializations of Vehicle; for example Sports Car and Flatbed Truck. Only objects of the class Flatbed Truck need provide a mechanism to deliver construction materials; sports cars, which are ill suited to that sort of work, need only drive fast.


This issue is one of the motivating factors behind prototypes. Unless one can predict with certainty what qualities a set of objects and classes will have in the distant future, one cannot design a class hierarchy properly. All too often the program would eventually need added behaviors, and sections of the system would need to be re-designed (or refactored) to break out the objects in a different way.[citation needed]

Experience with early OO languages like Smalltalk showed that this sort of issue came up again and again. Systems would tend to grow to a point and then become very rigid, as the basic classes deep below the programmer's code grew to be simply "wrong". Without some way to easily change the original class, serious problems could arise.[citation needed]


Dynamic languages such as Smalltalk allowed for this sort of change via well-known methods in the classes; by changing the class, the objects based on it would change their behavior. But in other languages like C++ no such ability exists, and making such changes can actually break other code, a problem known as the fragile base class problem. In general, such changes had to be done very carefully, as other objects based on the same class might be expecting this "wrong" behavior: "wrong" is often dependent on the context.


In Self, and other prototype-based languages, the duality between classes and object instances is eliminated.

Instead of having an "instance" of an object that is based on some "class", in Self one makes a copy of an existing object, and changes it. So Porsche 911 would be created by making a copy of an existing "Vehicle" object, and then adding the drive very fast method. Basic objects that are used primarily to make copies are known as prototypes. This technique is claimed to greatly simplify dynamism. If an existing object (or set of objects) proves to be an inadequate model, a programmer may simply create a modified object with the correct behavior, and use that instead. Code which uses the existing objects is not changed.

Like most programming languages JavaScript has a type system but its dynamically determined by the runtime environment, its types are associated with value not with variables.

Some examples would be handy right about now

Since essentially everything in JavaScript is an object it would be nice to have some familiarity to it.


var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};


Here in the above JSON example, object is created using object literal syntax, which is comma-separated list of property/value pairs within curly braces. The variable name in JavaScript could be any valid identifier or string and value could be constant or JavaScript expression. Since JavaScript is dynamically typed, variables are declared using var keyword(see above example). You could also declare variables without the var keyword but that would mean that scope of the variable is global.

Note: This post will not look into scoping and namespace but it’s really important to have that knowledge especially when building frameworks.

Here is another example from Prototype.js

var Prototype = {
Version: '1.6.0', //Constant value
Browser: {
IE: !!(window.attachEvent && !window.opera), //javascript expression
Opera: !!window.opera,
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && naviga
tor.userAgent.indexOf('KHTML') == -1,
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
},
...
...
};



Here in this example we are creating Prototype object using object literal syntax and "Version" is one of the property of the Prototype object with value of "1.6.0".

Objects are created when JavaScript interpreter evaluates the object literals. Once the object is created you can access its properties using the "." operator.
For Example


myJSONObject.ircEvent (produces: "PRIVMSG")
Prototype.IE (produces: true or false based on browser)


We should note that object properties doesn't have to be boolean or string, it could be another object as well. In the case of Prototype, "Browser" is a property and it is also an object with properties like IE, Opera, Webkit etc.

In the re-introduction section we discussed about the nature of the prototype based languages and how it encourages programmers to evolve their existing objects. In JavaScript we can create properties when we need them by simply assigning value to it.

Example from scriptaculous/unittest.js

var Test = {} //creating a empty object
Test.Unit = {}; //creating a new Unit property to Test object
// security exception workaround
Test.Unit.inspect = Object.inspect; //adding a new property to Unit object

In the above example we are creating an empty Test object without any property but moment we do Test.Unit = {}, it is creating a new property called Unit inside the Test object. We could also delete prop-erties from object on the fly using "delete" operator.


Earlier we looked how objects are created and how to access object properties using "." operator but we haven't formally defined JavaScript object yet.


In JavaScript, object is an unordered collection of properties. What it means is, we can loop through the object properties and access them as associative array using [] operator. This was very confusing to me before I understood how JavaScript objects are defined.


Example from scriptaculous/effect.js

//inspect property inside some object

inspect: function() {
var data = $H(); //some function, yes $ is allowed
//looping through all the properties defined inside this object
for(property in this)

if (!Object.isFunction(this[property])) //here object property is accessed as an array.
data.set(property, this[property]);
return ...;
}

Using "[]" operator has one advantage over the "." operator because the name of the property is expressed as string and could be manipulated in runtime.

someObject["someProperty" + "_en"]

Before we leave associative arrays, I like to mention that JavaScript also has a concept of array and it is defined as an ordered collection of values. Since JavaScript is dynamically typed we could create array with many different types, here is an example

var someArray = [ "this", "is", [1], way] //way is some variable already defined

JavaScript also defines additional methods like reverse, sort, slice, push, pop and others (complete list of methods and properties) for ar-ray. If we take a look at the list of methods it could be surprising to see methods like push and pop as if we are using stack instead of ar-ray. JavaScript arrays could be used as stack by pushing an element and popping an element.

Example from prototype.js


keys: function(object) {
var keys = [];

for (var property in object)
keys.push(property);

return keys;
},
values: function(object) {

var values = [];
for (var property in object)
values.push(object[property]);
return values;
}


In this code snippet we are pushing property names to keys array and pushing property values to values array.


Its quite similar to Ruby where array could also be used a stack but unlike Java where there is separate class for Array and Stack. It al-most feels like dynamic languages have their own design principles separate from other languages. Advocates of
Humane interfaces would argue that there could be multiple usage of an array, as an array or as a stack and hence we see methods like push and pop.

Labels