3.1. Defining Classes in Javascript

Defining classes in Javascript used to be quite mysterious for a beginner. There was no class statement, in fact, technially Javascript did not have the idea of class as a factory for making objects. Javascript was a prototypal language.

Prototypal inheritance is a form of object-oriented code reuse. Javascript is one of the only [mainstream] object-oriented languages to use prototypal inheritance. Almost all other object-oriented languages are classical.

In classical inheritance, the programmer writes a class, which defines an object. Multiple objects can be instantiated from the same class, so you have code in one place which describes several objects in your program. Classes can then be organized into a hierarchy, furthering code reuse. More general code is stored in a higher-level class, from which lower level classes inherit. This means that an object is sharing code with other objects of the same class, as well as with its parent classes.

In the prototypal inheritance form, objects inherit directly from other objects. All of the business about classes goes away. If you want an object, you just write an object. But code reuse is still a valuable thing, so objects are allowed to be linked together in a hierarchy. In javascript, every object has a secret link to the object which created it, forming a chain. When an object is asked for a property that it does not have, its parent object will be asked… continually up the chain until the property is found or until the root object is reached. (http://stackoverflow.com/questions/186244/what-does-it-mean-that-javascript-is-a-prototype-based-language)

However, that made it difficult for developers used to classical object oriented programming to come to Javascript. In the latest version of Javascript that has changed for the better. Under the covers Javascript is the same, but we now have some “syntactic sugar to make life better for us.”

We will explore object oriented programming in Javascript by implementing a fraction class.

Here is a mostly complete implementation of a Fraction class in Python that we will refer to throughout this section:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class Fraction:

    def __init__(self,top,bottom):

        self.num = top        #the numerator is on top
        self.den = bottom     #the denominator is on the bottom


    def __repr__(self):
        if self.num > self.den:
            retWhole = self.num / self.den
            retNum = self.num - (retWhole * self.den)
            return str(retWhole) + " " + str(retNum)+"/"+str(self.den)
        else:
            return str(self.num)+"/"+str(self.den)

    def show(self):
        print self.num,"/",self.den

    def __add__(self,otherfraction):
        # convert to a fraction
        otherfraction = self.toFract(otherfraction)

        newnum = self.num*otherfraction.den + self.den*otherfraction.num
        newden = self.den * otherfraction.den

        common = gcd(newnum,newden)

        return Fraction(newnum/common,newden/common)

    def __radd__(self,leftNum):
        otherfraction = self.toFract(leftNum)            
        newnum = self.num*otherfraction.den + self.den*otherfraction.num
        newden = self.den * otherfraction.den

        common = gcd(newnum,newden)

        return Fraction(newnum/common,newden/common)

    def __cmp__(self,otherfraction):

        num1 = self.num*otherfraction.den 
        num2 = self.den*otherfraction.num

        if num1 < num2:
           return -1
        else:
           if num1 == num2:
              return 0
           else:
              return 1

    def toFract(self,n):
        if isinstance(n,int):
            otherfraction = Fraction(n,1)
        elif isinstance(n, float):
            wholePart = int(n)
            fracPart = n - wholePart
            # convert to 100ths???
            fracNum = int(fracPart * 100)
            newNum = wholePart * 100 + fracNum
            otherfraction = Fraction(newNum,100)
        elif isinstance(n,Fraction):
            otherfraction = n
        else:
            print "Error: cannot add a fraction to a ", type(n)
            return None
        return otherfraction

#gcd is a helper function for Fraction

def gcd(m,n):
    while m%n != 0:
        oldm = m
        oldn = n

        m = oldn
        n = oldm%oldn

    return n

The instance variables (data members) we will need for our fraction class are the numerator and denominator. Of course in Python we can add instance variables to a class at any time by simply assigning a value to objectReferenc.variableName

Before we go any further lets look at how we would have defined the Fraction class in all the other versions of Javascript prior to the most recent. Its important that you understand this too as there are billions of lines of code written the old way.

3.1.1. Methods or Member Functions

Now we come to one of the major differences between Javascript and Python. The Python class definition used the special methods for addition, and comparison that have the effect of redefining how the standard operators behave. In Javascript there is no operator overloading. So we will have to write member functions to do addition, subtraction, multiplication, and division. Lets begin with addition.

Adding methods to your class is easy and the syntax is very clean. But it may feel a little strange to not have the word function or def in front of the method name. In all method the word this refers to the current object. Just like self does in Python. You will notice that you do NOT have to supply this as the first parameter to each method!

Next Section - 3.2. Inheritance