Object-Oriented JavaScript

Object-Oriented JavaScript

by Tim Huegdon

May 25, 2006


Following on from my earlier post, “Object-Oriented Concepts,” it’s time we started to have a look at some examples of execution. I’m going to start with Javascript because I believe this to have widest appeal - PHP, as a server-side language, is probably of interest to fewer developers so I’ll cover it later.

So without further ado, here’s how to objectify your javascript…

Objects in Javascript

Although Javascript shouldn’t be classed as an object-oriented language, pretty much everything within it is object based; from DOM scripting (Document Object Model) through to specific built-in objects such as Image and Date. This basically means that we can adopt some OOP concepts but not all.

Javascript handles objects in a number of ways; a developer can define an object and then instantiate with the new operator, a developer can declare an object on the fly using the object literal or a developer can extend an existing object (either built-in or user-defined) using its prototype.

In fact, even data-types that can be declared literally, such as arrays and strings, can also be declared as objects. This is mainly so that object methods can be applied to literal values when needed. Javascript does this by temporarily converting your literal into an object. A good example would be the String.length method.

Sounding complicated? Don’t worry, it’s really very easy. Let’s start getting our hands dirty…

The Object Literal

In programmer-speak, a “literal” is any value declared literally. Good examples would be string literals, array literals and boolean literals - the literal is the part after the “=” assignment operator:

// String literal
var my_string = "2468 This is a string";
// Array literal
var my_array = ['element1', 'element2', 'elephant'];
// Boolean literal
var my_boolean = true;

As a developer, you probably use these methods day-in, day-out; it still amazes me, however, how many programmers I speak to that don’t know the correct terminology!

In Javascript, we can also declare objects as a literal:

function getArea(radius)
{
// return the radius of our circle using the
// PI attribute of the built-in Math object
return (radius * radius) * Math.PI;
}
var circle = {
radius : 9,
getArea : getArea(this.radius)
};

Here we’ve defined an object, circle, with a radius of 9. If we wanted to obtain the area of our circle, we could use the following line of code:

var my_radius = circle.getArea();

Fantastic! We’ve got ourselves a circle; but what happens when we want to declare more circles, all with varying radii?

Imagine we want to create lots of circle objects using our object as a base - if we’ve declared using the object literal, we’re not able too. That’s the difference between objects and classes ; if we want our object to behave more like a class (which, unfortunately, aren’t really supported in Javascript even though we can mimic the behaviour), we need to use objects that utilise the new operator.

Note: For more information on the object literal, I recommend reading Chris Heilmann’s “Show Love to The Object Literal,” and Dustin Diaz’s “JSON for the Masses.”

The new Operator

The new operator creates an instance of any built-in or user-defined object - basically allowing us to re-use a user-defined obect (much like the behaviour of a class). Here are a couple of examples using built-in objects:

// Create a date object
var obj_today = new Date();
// Preload an image using the Image object
var obj_supper = new Image();
obj_supper.src = 'thelastsupper.jpg';

Take note that Javascript’s built-in objects do not always use a proper class interface - ie. you can set attributes without using a method. In most OOP languages this is considered bad practice and you can often prevent it with the use of access modifiers (public, private, protected). Even though Javascript let’s us get away with this method when using its built-in objects, I personally tend to write a proper interface for my own objects.

Ok, so that’s how you declare using the built-in objects, but what about something user-defined?

When using the new keyword to declare user-defined objects, the objects require a constructor. Object structure (including an object’s constructor) is handled somewhat differently to most languages in Javascript. Here’s the syntax for defining this type of object:

function circle(radius)
{
this.radius = radius;
this.getArea = getArea;
// Don't forget that a constructor should
// always retain a valid state - so it should
// always return true
return true;
}
function getArea()
{
// return the radius of our circle using the
// PI attribute of the built-in Math object
return (this.radius * this.radius) * Math.PI;
}

In the example above, you’ll notice that the syntax is almost completely identical to declaring a function. This function is the constructor of our object and attributes and methods are declared within it, using the this keyword.

Notice the Math object doesn’t need to be instantiated before we can use it - this is simply because it’s special and is always available for use.

We can now instantiate our object using the new operator as before:

var obj_pizza = new circle(9);

And we can work out the area of our circle using the following line of code:

var flt_area = obj_pizza.getArea();

Encapsulation

There is one problem with the above definitions of an object, however, and that’s the lack of encapsulation. If we were to include another piece of code that used a getArea() function (for instance a triangle object), our circle object’s getArea() method would be over-written. To better encapsulate our methods, we can define our objects either literally like so:

var circle = {
radius : 9,
getArea : function()
{
return (this.radius * this.radius) * Math.PI;
}
};

Or non-literally like so:

function circle(radius)
{
this.radius = radius;
this.getArea = function()
{
return (this.radius * this.radius) * Math.PI;
};
return true;
}

In both cases this limits the scope of each getArea() method to each circle object.

Inheritance and prototype

The prototype property is a useful feature in Javascript - it basically allows us to add attributes or methods to an object. This is a form of inheritance.

As a quick example of prototype in use, let’s add a function to work out circumference:

function circle(radius)
{
this.radius = radius;
this.getArea = function()
{
return (this.radius * this.radius) * Math.PI;
};
return true;
}
// Add our new method
circle.prototype.getCircumference = function()
{
return this.radius * Math.PI * 2;
}
// Instantiate our object
var my_pizza = new circle(9);
// Call our new method
var flt_pizza_circ = my_pizza.getCircumference();

“But wait, ” I hear you cry, “what if we want to inherit and entire object?”

Not a problem, prototype can handle this like so:

// Declare two objects - we're going to want Lion to
// inherit from cat
function cat()
{
this.eyes = 2;
this.legs = 4;
this.diet = 'carnivore';
return true;
}
function lion()
{
this.mane = true;
this.origin = 'Africa';
return true;
}
// Now comes the inheritance
lion.prototype = new cat();
// We can now obtain lion.diet
var simba = new lion();
var simba_diet = simba.diet;

Ok, so now that we understand inheritance (you do understand, right?), let’s take a look composition.

Composition

Association

Association, in Javascript, is pretty straight forward. Here’s an example:

// Define an object
function brick()
{
return true;
}
// Define an object
function wall()
{
this.brick1 = new brick();
this.brick2 = new brick();
this.brick3 = new brick();
return true;
}

Just like the pseudo-code example in my earlier post, we can see that the object “wall” now contains three instances of the “brick” object. This is association - the wall object “has” three bricks.

Now let’s take a look at aggregation.

Aggregation

Aggregation, as a relationship, is reliant on the ability to pass object and function parameters by reference. This basically means that a parameter represents the ACTUAL object passed and not just a copy. Thankfully, Javascript handles all parameters in this way - which makes our aggregation relationship nice and easy:

function person
{
return true;
}
function car(driver)
{
this.driver = driver;
return true;
}
var me = new person();
var myMotor = new car(me);

This relationship allows us to “use” the “me” object within our “myMotor” object. We could also use the “me” object in any other objects that require it - and we’d only need that single instantiation. This is immensely helpful when we’re using objects that control behaviours such as XmlHttpRequest.

Update: Thanks to Jonathan Snook, I’ve recently discovered that Javascript doesn’t pass all parameters by reference - in fact working out how Javascript has handled your parameter can be quite confusing. In our particular case, the parameter is passed by reference because it is an object. When we’re not working with objects, this might not be the case. For more detailed information, please take a look at Jonathan’s excellent article, “Javascript: Passing by Value or by Reference.”

Polymorphism

Due to it’s object-based nature, Javascript handles polymorphism very well. Take a look at the following example:

function circle(radius)
{
this.radius = radius;
this.getArea = function()
{
return (this.radius * this.radius) * Math.PI;
};
return true;
}
function rectangle(width, height)
{
this.width = width;
this.height = height;
this.getArea = function()
{
return this.width * this.height;
};
return true;
}

Both objects have a getArea() method, but both methods carry out different calculations. This is polymorphism in action.

Summary

So that’s a brief guide to adopting OOP practices in Javascript; I think you’ll agree that it adds real power when dealing with complicated scripts. However, that raises a common issue with OOP - you shouldn’t just use it for the sake of it. In fact, I often find that developers who are using these practices for everything are often the same developers who don’t understand the concepts fully.

My next OOP post will be regarding object-oriented PHP but, after an inquisitive email from Nate Logan, I also intend writing a piece about abstraction - the practice of reducing a process down to it’s root concepts and modelling them in the programming language of your choice.

Build sophisticated web applications by mastering the art of Object-Oriented Javascript About This Book Learn popular Object-Oriented programming (OOP) principles and design patterns to build robust apps Implement Object-Oriented concepts in a wide range of frontend architectures Capture objects from real-world elements and create object-oriented code that represents them Learn the latest ES6 features and how to test and debug issues with JavaScript code using various modern mechanisms Who This Book Is For JavaScript developers looking to enhance their web developments skills by learning object-oriented programming. What You Will Learn Get acquainted with the basics of JavaScript language constructs along with object-oriented programming and its application. Learn to build scalable server application in JavaScript using Node.js Generate instances in three programming languages: Python, JavaScript, and C# Work with a combination of access modifiers, prefixes, properties, fields, attributes, and local variables to encapsulate and hide data Master DOM manipulation, cross-browser strategies, and ES6 Identify and apply the most common design patterns such as Singleton, Factory, Observer, Model-View-Controller, and Mediator Patterns Design applications using a modular architecture based on SOLID principles In Detail JavaScript is the behavior, the third pillar in today's paradigm that looks at web pages as something that consists of : content (HTML), presentation (CSS), and behavior (JavaScript). Using JavaScript, you can create interactive web pages along with desktop widgets, browser, and application extensions, and other pieces of software. Object-oriented programming, which is popularly known as OOP, is basically based on the concept of objects rather than actions. The first module will help you master JavaScript and build futuristic web applications. You will start by getting acquainted with the language constructs and how to organize code easily. You develop concrete understanding of variable scoping, loops, and best practices on using types and data structures, as well as the coding style and recommended code organization patterns in JavaScript. The book will also teach you how to use arrays and objects as data structures. By the end of the book, you will understand how reactive JavaScript is going to be the new paradigm. The second module is an easy-to-follow course, which includes hands-on examples of solutions to common problems with object-oriented code. It will help to identify objects from real-life scenarios, to protect and hide data with the data encapsulation features of Python, JavaScript, and C#. You will discover the advantage of duck typing in both Python and JavaScript, while you work with interfaces and generics in C#. With a fair understanding of interfaces, multiple inheritance, and composition, you will move on to refactor existing code and to organize your source for easy maintenance and extension. The third module takes you through all the in-depth and exciting futures hidden behind the facade. You should read through this course if you want to be able to take your JavaScript skills to a new level of sophistication. Style and approach This course is a comprehensive guide where each chapter consists of best practices, constructive advice, and few easy-to-follow examples that will build up your skills as you advance through the book. Get object oriented with this course, which takes you on a journey to get acquainted with few useful hands-on tools, features, and ways to enhance your productivity using OOP techniques. It will also act as a reference guide with useful examples on resolving problems with object-oriented code in Python, JavaScript, and C#. Table of Contents Chapter 1: Javascript Primer Chapter 2: Functions, Closures, And Modules Chapter 3: Data Structures And Manipulation Chapter 4: Object-Oriented Javascript Chapter 5: Javascript Patterns Chapter 6: Testing And Debugging Chapter 7: Ecmascript 6 Chapter 8: Dom Manipulation And Events Chapter 9: Server-Side Javascript Chapter 10: Objects Everywhere Chapter 11: Classes And Instances Chapter 12: Encapsulation Of Data Chapter 13: Inheritance And Specialization Chapter 14: Interfaces, Multiple Inheritance, And Composition Chapter 15: Duck Typing And Generics Chapter 16: Organization Of Object-Oriented Code Chapter 17: Taking Full Advantage Of Object-Oriented Programming Chapter 18: Object-Oriented Javascript Chapter 19: Primitive Data Types, Arrays, Loops, And Conditions Chapter 20: Functions Chapter 21: Objects Chapter 22: Prototype Chapter 23: Inheritance Chapter 24: The Browser Environment Chapter 25: Coding And Design Patterns Chapter 26: Reserved Words Chapter 27: Built-In Functions Chapter 28: Built-In Objects Chapter 29: Regular Expressions
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值