![]() |
Web Development »
Client side scripting »
General
Intermediate
License: The Code Project Open License (CPOL)
Introduction to Object-Oriented JavaScriptBy PerspxAn introduction to writing object-oriented structures in JavaScript |
Javascript, Windows, Linux, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Many JavaScript programmers overlook or do not know of the ability to write object-oriented JavaScript. Whilst not conventionally an object-oriented language, JavaScript is a prototype-based language, which means that inherited classes are not derived directly from a base class, but rather are created by cloning the base class which serves as a prototype. This can be used to one's advantage in implementing encapsulation, inheritance and polymorphism in JavaScript, therefore creating a sense of object-orientation.
Object-oriented JavaScript also has several advantages. As it is an interpreted language, it means that methods and properties can be added to the class at any time, and do not have to be declared in the class constructor, like other object-oriented languages such as C++. As JavaScript supports variable data types, class properties do not have to take a fixed data type (such as boolean or string) but rather can be changed at any time. Furthermore, object-oriented JavaScript is more flexible and efficient than procedural JavaScript, as objects fully support encapsulation and inheritance and polymorphism can be implemented using the prototype property.
Although this is an introductory article to object-oriented JavaScript, it would be beneficial to have an understanding of object-oriented programming, as this article does not go into this aspect in too much detail. However, a list of key object-oriented programming terms are listed and defined below for some guidance in this respect.
Several key terms will be used in this article which are summarized below:
A basic class can be implemented very easily in JavaScript. All that must be done in order to define a class is for a function to be declared:
<script language="Javascript">
..
function MyClass()
{
}
..
</script>
These three lines of code create a new object called MyClass, instances of which can be created with the new operator, such as:
var c = new MyClass();
The function MyClass also acts as the class constructor, and when a new instance of that class is called with the new operator, this function is called.
This code so far is just a simple class with only its constructor declared. To add properties to the class, we use the this operator, followed by the name of the property. As previously stated, methods and properties can be created anywhere in JavaScript, and not just in the class constructor. Here is an example of adding properties to MyClass.
..
function MyClass()
{
this.MyData = "Some Text";
this.MoreData = "Some More Text";
}
..
These properties can be accessed by:
var c = new MyClass();
alert(c.MyData);
This piece of code adds the property MyData and MoreData to the class. This can be accessed anywhere within the class constructor and the class methods using the this operator, so MyData can be accessed by using this.MyData. Also note that unlike some object-oriented languages, class properties are accessed with a . and not a ->. This is because JavaScript does not differentiate between pointers and variables. If the class reference is stored in a variable when created, then the class properties can be accessed by the variable name followed by a . then the name of the class property, in this example myData, which is accessed with c.MyData.
As said earlier in the article, class methods are created using the prototype property. When a method is created in a class in JavaScript, the method is added to the class object using the prototype property, as shown in the following piece of code:
..
function MyClass()
{
//Any properties created here
}
MyClass.prototype.MyFunction = function()
{
//Function code here
}
..
For clarity, the method here is created by using = function(). Equally, the method can be created by declaring function MyClass.prototype.MyFunction(). What this code does is make MyFunction a method of MyClass using the prototype property. This then gives MyFunction access to any other methods or properties created in MyClass using the this operator. For example:
..
function MyClass()
{
this.MyData = "Some Text";
}
MyClass.prototype.MyFunction = function(newtext)
{
this.MyData = newtext;
alert("New text:\n"+this.MyData);
}
..
This piece of code creates the MyClass class, then creates a property called MyData in the class constructor. A method, called MyFunction is then added to the MyClass object, using the prototype operator, so that it can access the MyClass properties and methods. In this method, MyData is changed to newtext, which is the only argument of the method. This new value is then displayed using an alert box.
Encapsulation is a useful part of object-oriented programming that "encapsulates" or contains data in an instance of a class from the data in another instance of the same class. This is why the this operator is used within a class, so that it retrieves the data for that variable within that instance of the class.
Encapsulation is implemented in JavaScript by separating instance data within a class. However, there is no varying scale of encapsulation through the public, protected and private operators. This means that access to data cannot be restricted, as seen in other object-oriented programming languages. The reason for this is that in JavaScript it is simply not necessary to do so, even for fairly large projects. As of this, class properties and methods can be accessed from anywhere, either inside the class or outside of it.
An example of encapsulation can be shown below:
..
function MyClass()
{
this.MyData = "Some Text";
}
MyClass.prototype.MyFunction = function(newtext)
{
this.MyData = newtext;
alert("New text:\n"+this.MyData);
}
..
var c = new MyClass();
c.MyFunction("Some More Text");
var c2 = new MyClass();
c2.MyFunction("Some Different Text");
If called, c.MyData would return "Some More Text" and c2.MyData would return "Some Different Text", showing that the data is encapsulated within the class.
Encapsulation is an important part of object-oriented programming, so that data in different instances of a class are separate from one another; this is implemented in JavaScript by using the this operator. However, unlike other object-oriented programming languages, JavaScript does not restrict access to data within an instance of a class.
As said earlier in the article, there is no direct inheritance in JavaScript, as it is a prototype language. Therefore, for a class to inherit from another class, the prototype operator is used, to clone the parent class constructor, and in doing so, inheriting its methods and properties. The parent class constructor is also called in the subclass's constructor, to apply all of its methods and properties to the subclass, as shown in the code below:
..
//Parent class constructor
function Animal(name)
{
this.name = name;
}
//Inherited class constructor
function Dog(name)
{
Animal.call(this, name);
}
Dog.prototype = new Animal();
Dog.prototype.ChangeName(newname)
{
this.name = newname;
}
..
In the code example above, two classes are created — a base class called Animal and a subclass called Dog which inherits from Animal. In the base class constructor, a property called name is created, and set a value passed to it.
When an inherited class is constructed, two lines of code are needed to inherit from the base class, as demonstrated with Dog:
Animal.call(this, name);
This line of code is called from within the subclass's constructor. call() is a JavaScript function which calls a function in the specified context (the first argument). Arguments needed by the called function are passed also, starting from the second argument of call(), as seen with name. What this means is that the base class constructor is called from within the subclass constructor, therefore applying the methods and properties created in Animal to the subclass.
The second line of code needed to inherit from a base class is:
Dog.prototype = new Animal();
What this line of code does is set the prototype for the inherited class (which will clone the parent constructor when used) to be a new instance of the parent class, therefore inheriting any methods or properties in methods in the subclass.
Notice also that once a subclass has inherited from a parent class, any data that needs to be accessed from the parent class can be accessed using the this operator, from within the subclass, as the methods and properties are now part of the subclass object.
Like properties, methods can also be inherited from a parent class in JavaScript, similar to the inheritance of properties, as shown below:
..
//Parent class constructor
function Animal(name)
{
this.name = name;
}
//Parent class method
Animal.prototype.alertName = function()
{
alert(this.name);
}
//Inherited class constructor
function Dog(name)
{
Animal.call(this, name);
this.collarText;
}
Dog.prototype = new Animal();
Dog.prototype.setCollarText = function(text)
{
this.collarText = text;
}
..
An inherited method can be called as so:
var d = new Dog("Fido");
d.alertName();
This would call alertName(), which is an inherited method of Animal.
Classes that inherit from another class can be called in JavaScript as a base class would be called, and methods and properties can be called similarly.
var d = new Dog("Fido"); //Creates an instance of the subclass
alert(d.name); //Retrieves data inherited from the parent class
d.setCollarText("FIDO"); //Calls a subclass method
Methods that are inherited in a subclass can also be called similarly with the variable name in place of the this operator:
var d = new Dog("Fido"); //Creates an instance of the subclass
d.alertName(); //Calls the inherited method
Inheritance is the one of three important concepts of object-oriented programming. It is implemented in JavaScript using the prototype and call() functions.
Polymorphism is an extension on the principle of inheritance in object-oriented programming and can also be implemented in JavaScript using the prototype operator. Polymorphism is where a subclass of a class can call the same generic inherited function in its own context. For example:
..
//Parent class constructor
function Animal(name)
{
this.name = name;
}
Animal.prototype.speak = function()
{
alert(this.name + " says:");
}
//Inherited class "Dog" constructor
function Dog(name)
{
Animal.call(this, name);
}
Dog.prototype.speak = function()
{
Animal.prototype.speak.call(this);
alert("woof");
}
//Inherited class "Cat" constructor
function Cat(name)
{
Animal.call(this, name);
}
Cat.prototype.speak = function()
{
Animal.prototype.speak.call(this);
alert("miaow");
}
..
This code means that if an instance of Dog is called and then Dog's speak() function is called, it will override the parent class's speak() function. However, although we want to do something different with each subclass's version of speak(), we want to call the parent class's generic speak() function, through Animal.prototype.speak.call(this);, which calls the inherited function in the context of the subclass. Then after that we do something else with it, which for Dog is alert("woof"); and for Cat is alert("miaow");
If called, this would look like:
var d = new Dog("Fido"); //Creates instance of Dog
d.speak(); //Calls Dog's speak() function
var c = new Cat("Lucy"); //Creates instance of Cat
c.speak(); //Calls Cat's speak() function
The first two lines would alert "Fido says:" (the parent class's speak() function) followed by "woof" (Dog's speak() function).
The second two lines would alert "Lucy says:" (the parent class's speak() function) followed by "miaow" (Cat's speak() function).
Polymorphism is a very useful part of object-oriented programming, and whilst in this article it is not pursued too deeply, the principles remain constant and can be applied like this in most aspects of polymorphism in JavaScript.
After reading this article you should be able to:
This is just an introductory article, but I hope you can use these learned skills for more complicated object-oriented structures.
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 5 Aug 2008 Editor: Deeksha Shenoy |
Copyright 2008 by Perspx Everything else Copyright © CodeProject, 1999-2010 Web22 | Advertise on the Code Project |