Object-Oriented JavaScript: Part 2 | WebReference

Object-Oriented JavaScript: Part 2


Object-Oriented JavaScript: Part 2

By Cristian Darie, Bogdan Brinzarea

Digg This Add to del.icio.us

[This is an excerpt from the book, Microsoft AJAX Library Essentials: Client-side ASP.NET AJAX 1.0 Explained, by Cristian Darie, Bogdan Brinzarea. Published by Packt Publishing Ltd., 2007

JavaScript Classes

Not only can JavaScript functions contain other functions, but they can also be instantiated. This makes JavaScript functions a good candidate for implementing the concept of a class from traditional object-oriented programming. This is very helpful feature indeed, because JavaScript doesn't support the notion of a class in the classic sense of the word. Functions can be instantiated using the newoperator, such as in this example:

This line of code effectively creates an object named myHelloWorld, which represents an instance of the ShowHelloWorld() function. When the object is instantiated, the function code is executed, so creating the object has the same effect as calling ShowHelloWorld() as in the previous examples.

Here are a few facts that will help you port your C# OOP knowledge into the JavaScript world:

  • When a function is used as a class, its body code is considered to be the constructor. In classic OOP, the constructor is a special method that doesn't return anything, and that is called automatically when the object is created. The same effect happens in JavaScript when creating an instance of the function: its code executes. A C# constructor is equivalent to the code in the JavaScript function—without including any inner functions (whose code doesn't execute automatically).
  • In C# constructors can receive parameters, and also in JavaScript. If the code in a function represents the "class constructor", the parameters received by that function play the role of constructor parameters.
  • Class fields in JavaScript are created and referenced with the this keyword. In a JavaScript function, this.myValue is a public member of the function (class), while myValue is a local variable that can't be accessed through function instances. Also, the local variable is destroyed after the function executes, while class fields persist their value for the entire object lifetime.
  • Class methods that need to be accessible from outside the class need to be referred to using this as well. Otherwise the inner function will be regarded as a local function variable, rather than a "class" member.

We'll demonstrate these concepts by transforming the ShowHelloWorld() function that you saw earlier into a "real" class. We will:

  • Change the name of the function from ShowHelloWorld() to HelloWorld().
  • Add a parameter named hour to the function's "constructor" so that we tell the class the hour for which we need a greeting message, when instantiating it. If this parameter is passed when creating objects of the class, we store it for future use as a class field. If this parameter is not specified, the current hour of the day should be stored instead.
  • The method DisplayGreeting() of the class should not support the hour parameter any longer. Instead, it should display the greeting message depending on the hour field that was initialized by the constructor.

[ Why are we changing the name of the function? Remember, OOP is a style of coding, not a list of technical requirements that a language must support. JavaScript is considered an OOP-capable language because it supports an object-based programming style. In the OOP paradigm, a class should represent an entity, and not an action. Since we intend now to use ShowHelloWorld() as a class, we are changing its name to one that reflects this purpose. ]

Once your new class is created, you use it just as you'd use a C# class. For example, this is how you'd create a new class instance, and call its DisplayGreeting() method:

A possible implementation of the HelloWorld class is the following:

This code can be tested online. The HelloWorld class is formed of the constructor code that initializes the hour field (this.hour), and of the DisplayGreeting() method—this.DisplayGreeting(). Fans of the ternary operator can rewrite the constructor using this shorter form, which also makes use of the object detection feature that was discussed in Chapter 2:

[ The ternary operator is supported both by C# and JavaScript. It has the form (condition ? valueA : valueB). If the condition is true, the expression returns valueA, otherwise it returns valueB. In the shown example, object detection is used to test if a value was supplied for the hour parameter. If it was not, the current hour is used instead. ]

Class Diagrams

JavaScript classes, just like C# or VB.NET classes, can be described visually using class diagrams. There are standards such as UML (Unified Modeling Language), that can be used to model classes and the relationships between them. In this book we'll show quite a few class diagrams using the notation used by Visual Studio 2005. Using this notation, the HelloWorld class shown earlier would be described as shown in Figure 3-2.

The diagrams to this book follow typical conventions for C# classes, which don't translate to JavaScript exactly. For example, the diagram in Figure 3-2 says that the HelloWorld class has an integer field named hour. However, JavaScript doesn't support specifying data types for variables or class fields. The data type of the field makes the diagram helpful in specifying the intended purpose and type of the field, but that type isn't used in the actual implementation of the class.

The diagram also mentions the HelloWorld() constructor, which receives an integer parameter. As you know, JavaScript doesn't support "real" constructors. However, by reading the diagram you can tell that the HelloWorld() function receives a parameter named hour, which is supposed to be an integer value.

Appendix A contains more details about the conventions used in class diagrams throughout this book.