Skip to content

Latest commit

 

History

History
178 lines (128 loc) · 5.28 KB

object_oriented_programing.mkd

File metadata and controls

178 lines (128 loc) · 5.28 KB

Object Oriented JavaScript

For this section we're assuming that the reader is already familiar with Object Oriented programming.

Objects in Javascript

Almost certainly you're already familiar with objects in JavaScript even if you're not aware of it. In JavaScript, Hashes and Objects are the same thing. And they are everywhere!

var h = {"x": 10,
         "y": 20
        };

h["x"]
=> 10

h.x
=> 10

This is the "object literal" syntax, it provides a simple and clean syntax for making objects.

Similarly

var o = new Object();
o.x = 10;
o.y = 20;

o.x
=> 10

o["x"]
=> 10

Objects provide the foundation for much of JavaScript. It is the primary tool for code reuse, for namespacing, and certainly the most tool for storing and manipulating data. The goal of this document to talk about how we can use manipulate, and create objects to our advantage.

Building Your Own Objects

Although Javascript is Object Oriented, it differs from many other object oriented languages in some keys ways. This different style of Object Oriented programming is called "Prototype Based". In prototype based programming, there is no formal construct knowns as a class. Rather there are only Objects, and Constructor Functions. People coming from a background in other languages might find this confusing, and should be warned that many of your intuitions about the way these constructs behave could be wrong.

Constructor Functions

New types of objects are defined using Constructor functions.

var Speaker = function () {};

A Constructor Function is in all respects the same as any other function, it differs only in how it is called.

var s = new Speaker();

The use of the new keyword causes the creation of a new object referenced as 'this', and creates an implict return value of the object. Thus "this", becomes our brand new object.

Since the Constructor has access to "this", from the start, you can manipulate the returned object by manipulating "this".

var Microphone = function () {
  this.volume = 10;
}

var m = new Microphone();
m.volume
=> 10

We can also manipulate "this", by operating on the Constructors prototype object. The prototype object provides a starting point for "this", and is simply an ordinary object, attached to the "prototype" field of a Constructor Function.

var Amp = function (maxVolume) {
  this.maxVolume = maxVolume || 10;
  this.volume = 0;
}

Amp.prototype.setVolume(volume) {
  this.volume = Math.min(this.maxVolume, volume);
};

var a1 = Amp();
a.setVolume(11);
a.volume
=> 10

var a2 = Amp(11);
a.setVolume(11);
a.volume
=> 11

Inheritence

We've already seen that by manipulating a Constructor's prototype object you can attach a set of behaviors to all of its instances. To share those behaviors with another type of object, we can just assign an object to a prototype.

The most simple use of this might be to attach a shared data set to several types.

var SharedCableData = {
  length: 15,
  jack: 1/4
}

var SpeakerCable = function () {};
SpeakerCable.prototype = SharedCableData;

var MicCable = function() {}
MicCable.prototype = SharedCableData;

However this is possibly dangerous, as any future modifications to the prototype object of either type, will effect both types. In most cases that behavior is unexpected and is best to avoid it by making sure that the object you're assigning to a prototype is a new instance.

var SharedCableData = function() {};
SharedCableData.length = 15;
SharedCableData.jack = 1/4;

var PACable = function() {}
PACable.prototype = new SharedCableData();

By using the new keyword when assigning to a prototype, we avoid accidentally changing all other types using shared cable data.

Using that method, we can easily see how to share behavior between types. Below I make use of our previous Amp Constructor to build a PA. Which in this case is an Amp with the ability to be directionaly positioned.

var PA = function (maxVolume, direction) {
  this.maxVolume = maxVolume;
  this.direction = direction;
};

PA.prototype = new Amp();

PA.prototype.setDirection = function (direction) {
  this.direction = direction;
};

var pa = new PA(10, 180);
pa.setVolume(11);
pa.volume;
=> 10

pa.setDirection(90);
pa.direction;
=> 90;

Encapsulation

Encapsulation is the process or method of hiding data from users of your objects. By exposing only the set of methods that users will need, you limit your liability. It frees you to change the behavior of methods that are hidden, while making sure that code that depends on those objects keeps working.

Some languages provide tools to manage what is hidden and what is public, with special keywords like, "public", "private", "protected". JavaScript doesn't have any of these keywords yet encapsulation is still possible by use of the Constructor functions private scope.

As mentioned earlier, when you use the new keyword it creates an implicit return value of "this" on that function. When you set an explicit return, it takes precedence and over-rides that implicit return.

So let's look at an example.