Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Wednesday, February 10, 2016

Object prototypes in JavaScript

In this post we will try to understand how to make use of JavaScript's Object prototypes to achieve code re-use i.e. to do Object (Oriented) programming[1].

It would be very useful read this without thinking of Java's notions of OO.

In JavaScript, we do not need special constructs( such as classes)  to create instances/objects. If we want an object, we just create one like so
1
2
3
4
5
6
7
var myCar = {
 numGears: 4,
 drive: function(){
  console.log('driving');
 }
}
myCar.drive(); // driving
And then another
1
2
3
4
5
6
7
var yourCar = {
 numGears: 5,
 drive: function(){
  console.log('driving');
 }
}
yourCar .drive(); // driving
No classes, no new keyword, no constructor function... plain and simple.
We can do better.. you would have noticed that the drive method(its really just a regular function) is repeated in the objects. It is the exact same code.  As we all know, code duplication is the enemy of the programmer. 
To facilitate sharing this function across the 2 objects, lets first pull this function out into a separate object. Lets call this object CarPrototype
1
2
3
4
5
var CarPrototype = {
 drive: function(){
  console.log('driving');
 }
}
The way to read CarPrototype would be as the object where we would add common functionality of car-type objects. 
Its not accidental that I used the phrase "Prototype" in "CarPrototype". More on that soon.
Now to make use of this shared object among myCar and yourCar objects, we would conceptually need the following.



i.e. more generically stated, we need a way to link objects to other objects[2].

Object.create


There is language support to achieve the above linking using the Object.create[3] function
As the name indicates, its used to create objects. Lets re-create myCar and yourCar using this.
1
2
3
4
5
var myCar = Object.create(CarPrototype);
myCar.numGears = 4;

var yourCar = Object.create(CarPrototype);
yourCar.numGears = 5;
Lines 1 and 4 do the following couple of things:

  1. Create and return a new object just like the humble object literal - { }
  2. And also create the linkage (thats shown as a dotted arrow in the picture above) from myCar and yourCar to CarPrototype

This linkage is the one of the most important concepts in JavaScript. It is known as prototype relationship between objects. Hence the reason for me to name the shared object as CarPrototype

Good-to-know facts about the prototype link
  • It is referred to as [[Prototype]] in the official spec
  • It is available via the __proto__ property (pronounced as dunder-proto) like so: 
    • myCar.__proto__
  • It can also be accessed using the Object.getPrototypeOf function like so:
    • Object.getPrototypeOf(myCar)
  • It is often confused with the prototype property that functions have

Foot-note:

[1] It was tempting to title this post as Object-oriented programming in JavaScript.. but I realized that it would have disappointed the Java developers who would stumble across it in their search to understand how to create classes in JavaScript.
[2] Kyle Simpson has formalized this into what he terms as OLOO (Objects linked to Other Objects) in his excellent You dont know JS series. 
[3] I wanted to link to the MDN doc for this but I refrained from doing so because at the time of this writing, their example highlights a class-style pattern which at best leaves a reader confused and at worst could lead new developers into assuming that its the MDN-recommended way.

Monday, January 11, 2016

Class style programming in JavaScript: Part 2

In Part 1 of this post we explored the class style paradigm for developing modular code. I encourage reading it before continuing. Its ok if you dont want to, here is the tldr; bullet-point version:
  • Classes are not a language construct in JavaScript
  • Class-style programming can be simulated because of the language's flexibility
  • Function names are capital-cased but the upper-casing is convention-only i.e. to make them look like Java's class constructors. 
    • var Car = function() {};
  • Invoking these functions with the new keyword creates objects/instances
    • var myCar = new Car();
  • A prototype property exists on all functions. It is an object.
    • console.log(Car.prototype); // Object {}
  • Code(data/functions) that is meant to be shared across these different instances are added to the prototype property
    • Car.prototype.drive = function() { //do stuff };
All that said, we have to admit that the using the prototype property to achieve class-style programming feels nothing like using Java's classes. But that was the intent when the feature was added to the language i.e. to make it more familiar to Java programmers.
In this post, we will try to understand how we would achieve code re-use similar to Java's Class-based inheritance pattern. 
Continuing with our Car example .. if we needed a specialized version we could call it NextGenCar which essentially built upon the existing features. How would we model these requirements where NextGenCar needs the following:
  1. Its constructor to re-use Car's constructor and initialize additional instance properties
  2. Inherit all of Car's features
  3. to drive more efficiently than the current drive i.e. it needs to extend drive()
  4. to have a completely overhauled braking system i.e. it needs to override stop()
  5. to have a way to switch to driverless mode and back 
The code solution below is annotated with comments on how each of the above requirement is satisfied
 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
var NextGenCar = function(numGears, numWheels){
   // #1: Use the call method thats available on functions to mimic super constructor call
   Car.call(this, numGears); 
   // #1 Initialize additional properties
   this.numWheels = numWheels; 
}

// #2: Using Car's prototype as blue-print create a new object 
// and set it as NextGenCar's prototype 
// so that it inherits all methods of Car via Object [[Prototype]] linkage
NextGenCar.prototype = Object.create(Car.prototype);

NextGenCar.prototype.drive = function() {
   //#3: Use the call method to mimix a super call to the method on the "super-class"
   Car.prototype.drive.call(this); 
   console.log('more for the gallon'); 
}

NextGenCar.prototype.stop = function() {
   console.log('you said stop and i stopped before you finished saying'); // #4
}

// #5: New methods
NextGenCar.prototype.switchMode: function(mode){
   console.log('cruising in '+mode+' mode');
}

var myNextGenCar = new NextGenCar(4, 4);
myNextGenCar.switchMode('driverless'); //cruising in driverless mode'
I think the above code is definitely hard to understand and barely represents what we are trying to do.
Lets see if a picture helps..



(the dotted arrows indicate the prototype linkage between objects)

Did the picture help ?
maybe.. a little bit. But I think this exercise helps realize the futility of attempting class-style programming in a class-less world. There are better alternatives - Object Programming using prototypes and/or functional programming. I will explore the former in my next post.

All that said, it is still useful to understand constructor functions and the prototype property on functions because these are deeply entrenched in the language. There is also a class of problems that can be solved elegantly using ES6 classes only  and not using the alternatives mentioned above (and this will be a topic of a blog post for an other day)

References


Wednesday, September 23, 2015

JavaScript's new operator

In a previous post we explored the class-ical programming paradigm in JavaScript
The constructor pattern is a fundamental aspect of the class-ical paradigm
A constructor is code using which objects can be created from a class using the 'new' keyword
.
Under the hood, JavaScript uses it's prototypal mechanism to support this feature. In other posts I explore the prototypal form in depth. For now, lets try to understand how 'new' works:

Lets create a function Person to behave like a Java Class

1
2
3
4
5
function Person(first, last) {
  this.first = first;
  this.last = last;  
}
var s = new Person("Deepak", "Anand");

Here are the things that happened after the last line was executed:

  1. new creates a new object, lets call it this
  2. the (constructor) function Person is called like so: this.Person ("Deepak", "Anand")
  3. this is returned
Using upper-case for function-names that are used as constructors is convention only, not a language construct.

Now, what if you want methods in your "class"

Easy enough....

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function Person(first, last) {
  this.first = first;
  this.last = last;
  this.getFullName = function() {
    return this.first + ' ' + this.last;
  };
  this.getFullNameReversed = function() {
  return this.last + ', ' + this.first;
  };
}

This works, but is not very efficient. For every Person instance, 2 function objects are created.
The solution is to add methods to the function's prototype property like so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function Person(first, last) {
  this.first = first;
  this.last = last;
}
Person.prototype.getFullName = function() {
  return this.first + ' ' + this.last;
};
Person.prototype.getFullNameReversed = function() {
  return this.last + ', ' + this.first;
};

References:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

Thursday, March 5, 2015

Class style programming in JavaScript: Part 1

JavaScript does not have language support for classes in the same way that Java does[1]
But, JavaScript is a versatile language. It can be tailored to mimic different programming paradigms. The Java-style class-based programming pattern is quite popular. So much so, that there are dedicated modules in frameworks such as Dojo declare[2], Prototype's Class.create and the list goes on. This pattern is also commonly referred to as Object Oriented programming, which I think is a misnomer because it really is more about classes than objects. 
In JavaScript, functions play the role of..well.. plain old functions and also to create class-like entities.For this post, we are interested in the latter. When a function is invoked with the "new" keyword, it returns an object i.e. it acts as a constructor.
Lets look at an example:
1
2
3
4
5
6
7
8
9
var Car = function(numGears){
 this.numGears = numGears;
 this.drive = function(){
   console.log("driving");
 }
};

var myCar = new Car(4);
myCar.drive() //driving
Whoa.. the above type of Car cannot be stopped, because there is no method/mechanism in the Car function to do that.
Lets add a stop() method to that
1
2
3
myCar.stop = function(){
 console.log("stop");
}
Do you see a problem with this... yes, only myCar can be stopped now, not the rest of the cars coming out of the factory. Lets see if this assumption is true.
1
2
var yourCar = new Car(5);
yourCar.stop();// TypeError: Object [object Object] has no method 'stop'
So, we need this method on all cars that come out of the factory. If the stop() method were defined as part of the Car function definition in the first code snippet, then all new cars would "inherit" this, but how do we install a "stop" method now. The answer lies in the prototype property available on functions:
console.log(Car.prototype);// Object {}
The prototype property is available on all functions, but make sense only for functions that are used as constructors. The reason will be obvious when you understand their role.
The prototype property on functions point to an object which serves as the the blueprint of the objects created using that function. The newly created objects have a secret link to this blueprint.
But why is it empty in the example .. shouldnt we be seeing a drive() method on it ?
No, because we did not leverage this  prototype property to add the method to this blueprint. Look back at the first code snippet, the drive() method is defined like so:
this.drive  = function(){..
This results in every car instance getting its own copy of the drive() method. (Obviously this is not very efficient. We will correct this later.)
To understand how the prototype property works, lets add stopping functionality to the Car.
1
2
3
4
Car.prototype.stop = function(){
  console.log("stop");
}
yourCar.stop(); // stop
Note that unlike the drive() method, we added the stop() method to the prototype property. This has the effect that all instances get this method including the ones that were created before this method was added
So, that worked.  
Lets paint a picture to remember this better


If we were to redo the Car function from scratch, this is how it would look:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var Car = function(numGears){
 // per-instance properties
 this.numGears = numGears;
};

// shared code on prototype
Car.prototype.drive= function(){
  console.log("driving");
}
Car.prototype.stop = function(){
  console.log("stop");
}

var myCar = new Car(3)
myCar.drive(); // driving
myCar.stop(); // stop
This is quite strange-looking, very unlike a Java class.  But it is the way you are expected to do class-based programming in this language.
In another post, I will explore how code is shared by inheritance using the class style paradigm

[1] In the next version of the language i.e. in ES2015 / ES6, you can create classes using the class keyword. Here is a link where you you learn more about it:
Classes in JavaScript - My understanding is that it is mostly syntactic sugar that transforms into the above code.
[2] I originally intended to write about the Dojo declare feature, hence the url of this page name reads as "dojo-declare". The declare module in Dojo is used for creating Java-style classes. The widget framework  - Dijit uses this heavily.