|
Page 2 of 2
Production-quality C# implementation
In a production-quality C# implementation you may want to implement rows and columns as properties with get and set assessors, rather than public fields. That implementation, however, would make its JavaScript version more complicated than necessary for the purposes of our examples.
The Table class can be easily implemented in JavaScript as shown in the following code snippet, and it would resemble very much its C# version:
function Table (rows, columns) { // "constructor" this.rows = rows; this.columns = columns; // getCellCount "method" this.getCellCount = function() { return this.rows * this.columns; }; }
%20function%20Table%20%28rows%2C%20columns%29%20%0A%0D%0A%7B%20%0A%0D%0A%2F%2F%20%22constructor%22%20%0A%0D%0Athis.rows%20%3D%20rows%3B%20%0A%0D%0Athis.columns%20%3D%20columns%3B%20%0A%0D%0A%2F%2F%20getCellCount%20%22method%22%20%0A%0D%0Athis.getCellCount%20%3D%20function%28%29%20%0A%0D%0A%7B%20%0A%0D%0Areturn%20this.rows%20%2A%20this.columns%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%7D
After having declared the object, we can instantiate it by using the new operator and use its properties and methods:
var t = new Table(3,5); var cellCount = t.getCellCount();
var%20t%20%3D%20new%20Table%283%2C5%29%3B%20%0A%0D%0Avar%20cellCount%20%3D%20t.getCellCount%28%29%3B
There are a few subtle points you need to notice regarding the JavaScript implementation of Table:
You don't declare public members explicitly. You simply need to reference them using this, and assign some value to them; from that point on, they're both declared and defined.
JavaScript allows you to implement most of the design specifications defined in class diagrams, but the implementation can't reflect the specification as accurately as a C# implementation can. For example, the line Table (int rows, int columns) in the diagram in Figure 3-3 refers to the constructor of the class. In JavaScript, as you know, classes as implemented using functions neither have real constructors, nor support specifying data types for their parameters.
When objects are created, each object has its own set of data—to maintain its own state. However, C# and JavaScript are different in that in JavaScript functions are first-class objects. In C#, the "state" is made of the object's fields. The object functionality, as defined by its methods, is the same for all objects of the same type. For example, if you create many objects of the type Table in C#, each object will have its own set of rows and columns, but internally they all use the same copy of the getCellCount() method. In JavaScript, however, functions are treated like any other variable. In other words, creating a new Table object in JavaScript will result not only in creating a new set of rows and columns values, but also in a new copy of the getCellCount() method. Usually, you don't need (or want) this behavior.
The last mentioned problem is commonly referred to as a "memory leak", although technically it's just inefficient JavaScript object design. When we design our JavaScript "classes" as we do in typical OOP languages, we don't need each class to create its own set of methods. It's only state (fields) that need to be individual, and not methods' code. The good news is that JavaScript has a neat trick that we can use to avoid replicating the inner function code for each object we create: referencing external functions.
Referencing External Functions
In stead of defining member functions ("methods") inside the main function ("class") as shown earlier, you can make references to functions defined outside your main function, like this:
function Table (rows, columns) { // "constructor" this.rows = rows; this.columns = columns; // getCellCount "method" this.getCellCount = getCellCount; } // returns the number of rows multiplied by the number of columns function getCellCount() { return this.rows * this.columns; }
function%20Table%20%28rows%2C%20columns%29%20%0A%0D%0A%7B%20%0A%0D%0A%2F%2F%20%22constructor%22%20%0A%0D%0Athis.rows%20%3D%20rows%3B%20%0A%0D%0Athis.columns%20%3D%20columns%3B%20%0A%0D%0A%2F%2F%20getCellCount%20%22method%22%20%0A%0D%0Athis.getCellCount%20%3D%20getCellCount%3B%20%0A%0D%0A%7D%20%0A%0D%0A%2F%2F%20returns%20the%20number%20of%20rows%20multiplied%20by%20the%20number%20of%20columns%20%0A%0D%0Afunction%20getCellCount%28%29%20%0A%0D%0A%7B%20%0A%0D%0Areturn%20this.rows%20%2A%20this.columns%3B%20%0A%0D%0A%7D%20
Now, all your Table objects will share the same instance of getCellCount(), which is what you will usually want.
Trackback(0)

|