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.
Given a numerator and a denominator create a new Fraction.
When a fraction is printed it should be simplified.
Two fractions can be added or subtracted
Two fractions can be multiplied or divided
Two fractions can be compared
A fraction and an integer can be added together.
Given a list of Fractions that list should be sortable by the default sorting function.
Here is a mostly complete implementation of a Fraction class in Python that we will refer to throughout this section:
1class Fraction:
2
3 def __init__(self,top,bottom):
4
5 self.num = top #the numerator is on top
6 self.den = bottom #the denominator is on the bottom
7
8
9 def __repr__(self):
10 if self.num > self.den:
11 retWhole = self.num / self.den
12 retNum = self.num - (retWhole * self.den)
13 return str(retWhole) + " " + str(retNum)+"/"+str(self.den)
14 else:
15 return str(self.num)+"/"+str(self.den)
16
17 def show(self):
18 print self.num,"/",self.den
19
20 def __add__(self,otherfraction):
21 # convert to a fraction
22 otherfraction = self.toFract(otherfraction)
23
24 newnum = self.num*otherfraction.den + self.den*otherfraction.num
25 newden = self.den * otherfraction.den
26
27 common = gcd(newnum,newden)
28
29 return Fraction(newnum/common,newden/common)
30
31 def __radd__(self,leftNum):
32 otherfraction = self.toFract(leftNum)
33 newnum = self.num*otherfraction.den + self.den*otherfraction.num
34 newden = self.den * otherfraction.den
35
36 common = gcd(newnum,newden)
37
38 return Fraction(newnum/common,newden/common)
39
40 def __cmp__(self,otherfraction):
41
42 num1 = self.num*otherfraction.den
43 num2 = self.den*otherfraction.num
44
45 if num1 < num2:
46 return -1
47 else:
48 if num1 == num2:
49 return 0
50 else:
51 return 1
52
53 def toFract(self,n):
54 if isinstance(n,int):
55 otherfraction = Fraction(n,1)
56 elif isinstance(n, float):
57 wholePart = int(n)
58 fracPart = n - wholePart
59 # convert to 100ths???
60 fracNum = int(fracPart * 100)
61 newNum = wholePart * 100 + fracNum
62 otherfraction = Fraction(newNum,100)
63 elif isinstance(n,Fraction):
64 otherfraction = n
65 else:
66 print "Error: cannot add a fraction to a ", type(n)
67 return None
68 return otherfraction
69
70#gcd is a helper function for Fraction
71
72def gcd(m,n):
73 while m%n != 0:
74 oldm = m
75 oldn = n
76
77 m = oldn
78 n = oldm%oldn
79
80 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!