devxlogo

JavaScript as a Foundation Language for Your Web Apps

JavaScript as a Foundation Language for Your Web Apps

avaScript luminary Douglas Crockford defined JavaScript as “the world’s most misunderstood programming language.”

Characterized by some dubious design decisions, ambiguous syntax rules, and a troubled history (see Sidebar 1. A Brief History of Why JavaScript Makes Sense), JavaScript could have been dismissed as a second-class scripting language useful only for animating web pages. However, JavaScript has matured into one of the most ubiquitous and pervasive programming languages today, currently powering complex and highly interactive web applications. With JavaScript so widely distributed and so closely tied to the user experience, JavaScript skills are mandatory if you develop web applications nowadays.

This article explains why JavaScript is perfectly suited as a core, foundation language for your web applications. It introduces the lesser known and yet most powerful JavaScript features, and demonstrates how to leverage them to increase your productivity.

Even though you can use JavaScript in standalone interpreters and applications, this article concentrates on running it inside web pages. The following code shows the prototypical web page that you will write your code into throughout this article. It mimics a web application that you will enrich as you explore the features of JavaScript.

  	  

It makes no significant difference as far as the language goes whether it’s standalone or inside a page, but using the web page simplifies setup and testing. You just need to load the above code in your browser to test the code.

Procedural Programming in JavaScript
JavaScript supports multiple programming paradigms. Just like C, you can adopt procedural programming and layer your instructions one after another. JavaScript does not have namespaces (although there are ways to mimic them), so everything lives in a global one. Inside such a namespace, you can define variables and functions and execute them as shown here:

Notice that the code adopts some conventions that?even though not enforced by the interpreter?improve the reliability of the code. These include always declaring variables using the var keyword and always terminating statements with the semicolon.

Objects vs. Prototypes
If you are more familiar with object-oriented programming (OOP), you can adopt the OOP style in JavaScript as well. JavaScript does not support classical class-based OOP but a variant called prototype-based programming. The main difference between the two is that class-based languages such as Java distinguish between classes, which define the behavior exposed by the entities you define (i.e., the class methods), and objects, which contain the data such behaviors can be applied to (i.e., instances of the class).

Prototype-based languages do not have classes. They define only objects and the semantics surrounding how new objects can be created or derived from existing ones. Any two objects can be linked together into a relationship, where one object represents the “prototype” for the other in the sense that it defines the stub upon which the object builds its functionalities. Such links are used for data access and function resolution in a way that resembles traditional class inheritance: Each object delegates to its prototype whenever it is asked to access a variable or a function it doesn’t know. This paradigm, adopted by JavaScript, is called “delegation.” (Refer to this introduction to prototypes for a more thorough explanation.)

Listing 1 and Listing 2 illustrate the differences between class-based and prototype-based approaches. Listing 1 shows the definition and usage of a parent and child class in Java. Listing 2 shows the same definition in JavaScript using prototypes.

Listing 2 actually demonstrates a number of language features. First of all, look at the definition of the Compiler object. It is an anonymous function that operates on the this variable. The object itself is created using the new keyword. Behind the scenes, JavaScript creates an empty object when it encounters the new keyword, and then it invokes the anonymous function as a constructor, assigning the newly created object to the this variable so that the function can proceed to initialization. The code contains some more subtleties, but that is the high-level view.

Notice also how you create methods by attaching functions to objects, just like you would with regular variables. JavaScript functions are objects. This is one of the functional aspects of JavaScript, which in part behaves like pure functional languages such as Lisp.

The Compiler Object with a Better Use of Prototypes
The following statement from Listing 2 defines the delegation relationship between the two objects:

OptimizedCompiler.prototype = new Compiler();

Remember that OptimizedCompiler is a function, and each function contains a prototype attribute that you can use to explicitly declare who its prototype is. Even though this is formally an has-a relationship, because of the way JavaScript delegation works, it ends up working in the same way you would expect classical inheritance to work.

Notice also that the code assigns a newly instantiated object?not a class?as the prototype. This shows that JavaScript prototypes are mutable at any time, a feature that you will leverage later. Prototype delegation is also dynamic. After you establish a relationship, whenever you change some features of the prototype object, all the dependent objects that delegate to it will expose the new features immediately.

Because each function always has its prototype defined, you can move method definitions on it. Additionally, since JavaScript does not have private scopes (although you can mimic them using closures, which you will learn about soon), you can also remove accessor methods. With these change made, the Compiler object definition now reads as in Listing 3.

Object Literals in JavaScript
If you don’t need the benefits of prototypes and inheritance, you can simplify object creation by using literals. JavaScript objects are nothing more than collections of key value pairs, and you can create them using a simplified syntax. By using literals, you can also skip the definition of a constructor, which is superfluous in this example.

JavaScript is a dynamically typed language and therefore supports duck typing: You don’t have to declare function expectations in term of types, but rather in term of capabilities. You are free to pass whatever object you want to a function, as long as it fulfills the contract the function is going to exercise on the object.

By applying these two concepts, the example collapses into the following reduced notation:

// define the object literalvar c = {  languageName : "Java",   optimizationLevel : 4,  compile : function(code) { /* compile the code */ }};document.write(  "Got a " +   c.languageName +   "  with optimization level " +   c.optimizationLevel);// invoke the compile function on the object.// JavaScript doesn't require a static type// to identify the function and invoke it.var complexPieceOfCode = " ... ";c.compile(complexPieceOfCode);

Remember that all JavaScript prototypes are mutable. You can leverage this even to enrich standard classes as follows, where the even() method is added to the Number class:

Number.prototype.even = function() {  return this % 2 == 0;};e = new Number(4);o = new Number(5);e.even(); // trueo.even(); // false

Functions and Functional Programming
As you have seen, functions are first-class citizens in the JavaScript landscape. They are objects and therefore extensible and customizable. You also can pass them around as method parameters and assign them to variables.

JavaScript also supports closures. Closures represent the ability of functions to retain the context in which they were created, so that when invoked later they can still access the state information available within the scope at creation time.

Because such scopes are accessible only to the function to which they are associated, they offer a perfect way to avoid polluting the global namespace with symbols that are used only in a limited area. They also provide a way to implement private scopes (for example, limiting the visibility of some object fields).

These functional aspects add great expressive power to the language and allow you to define rich behaviors and patterns (callbacks, handlers, partials, currying, and many others) that are typical of more formalized functional languages such as Lisp. Listing 4 shows a mixed example of all these function features.

Newer JavaScript Features
So far, you have examined JavaScript features that are standardized in the ECMAScript 1.3 specification (which dates back to year 2000) and are supported by all modern browsers. However, the JavaScript language has continued to evolve, and some browser makers have proposed and introduced many new features with the expectation of making them available in the next ECMAScript specification.

For example, recent versions of Mozilla Firefox offer new functionalities that streamline the language a bit and borrow from other popular programming languages. This section presents a brief overview of the most notable additions. When you use these features, remember to specify the right version of JavaScript you want to use in your script header, as follows:

JavaScript 1.6 (supported by Firefox 1.5 and later versions) adds new methods to the system classes, such as Array, to enrich them with filtering and map/reduce capabilities. Listing 5 demonstrates some of these methods while this article contains a wider set of examples.

JavaScript 1.7 (supported since Firefox 2) introduces constructs such as generators and list comprehensions, which are popular in Python. Generators are specialized functions that generate (potentially unlimited) series of values and yield one value at a time when requested. They are useful for iterative algorithms. List comprehensions are a specific use of generators for quickly initializing arrays with defined sets of values. Listing 6 demonstrates generators and list comprehensions.

Take a look at the Firefox release notes for the various versions of the browser and their underlying JavaScript engines to learn more about these new features. Listing 7 provides a comprehensive example that uses many of these features.

Libraries and DOM Manipulation
When working on web applications, you can use JavaScript to affect all the aspects of the application:

  • The controller logic, which defines how to respond to user events
  • The presentation layer, which defines the look and feel and animated behaviors
  • The network layer, which handles communications and data transfer to and from the server

Even though you could implement all the handling code on your own, relying on existing libraries is usually better. These libraries provide multiple benefits:

  • They abstract away browser quirks and discrepancies.
  • They standardize access to the DOM and provide helper functions for frequent operations.
  • They implement popular functionalities (such as array iterators and cross-site AJAX calls) when the browser does not directly supported them or ECMA has not yet standardized them.

Popular libraries, such as JQuery or Prototype, leverage all the language features that you have learned so far, have an extensive community to support them, and are often included into other development frameworks, such as Ruby On Rails.

As an example, consider the snippet in Listing 8, which is built on top of JQuery. Among the things the library enables you to do are use complex CSS selectors to select DOM elements and chain multiple operations together.

2D Graphics
In addition to DOM manipulation, modern web applications rely heavily on the ability to display complex graphics such as charts and overlays along with text. To allow this in the past, you would use server-side calls to generate the images or embed Flash scripts in your pages. However, these approaches limit the possibilities for interaction with the user and/or add unnecessary complexity to the architecture.

If you want to remain in the JavaScript domain for your graphics-display solution, you can use the Canvas element. Canvas is a new HTML tag, originally introduced by Apple to provide advanced graphics to dashboard widgets. It can represent 2D primitives and you can use JavaScript to manipulate and animate its contents. All major browsers except Internet Explorer support Canvas, and you can use the ExCanvas library for IE. The following snippet creates two alpha-blended rectangles on the screen:

   

This is just a simple demonstration, but once you start exploring you will be amazed at all the possibilities. Check John Resig’s implementation of the Processing language, Algorithm in Ink, or even a playable version of Super Mario!

Only Scratched the Surface
You have gotten an overview of the JavaScript programming language, from its basic structure and underlying paradigms to its high-level constructs, concepts, libraries, and functionalities?all of which are powering the current generation of web applications. However, you have just scratched the surface; many topics still remain to be explored.

First of all, performance is a factor you should always consider when implementing your code. Even though modern and next-generation engines, like Mozilla’s TraceMonkey, Safari’s Squirrelfish, and Google’s V8, promise outstanding speeds and on-the-fly native compilation, you should always think about how to improve the performances of your application. This is even truer nowadays, as the browser handles more and more computing tasks on its own. Techniques like JavaScript minification and tools like Yslow and Cuzillion may help in your search for speed.

Also, this article focused on scripts that live within online web pages, but you may use JavaScript for server-side operations (like using standalone engines such as Mozilla Rhino). You can also employ plugins, like Gears, that provide support and JavaScript APIs for creating complete applications that can work offline and access local storage and computing power.

Each of these topics is worth studying further, but hopefully this article provided the core knowledge to help you get started.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist