Book Image

Mastering JavaScript Object-Oriented Programming

Book Image

Mastering JavaScript Object-Oriented Programming

Overview of this book

ECMAScript 6 introduces several new Object-Oriented features that drastically change the way developers structure their projects. Web developers now have some advanced OOP functionality at their disposal to build large-scale applications in JavaScript. With this book, we'll provide you with a comprehensive overview of OOP principles in JavaScript and how they can be implemented to build sophisticated web applications. Kicking off with a subtle refresher on objects, we'll show you how easy it is to define objects with the new ES6 classes. From there, we'll fly you through some essential OOP principles, forming a base for you to get hands-on with encapsulation. You'll get to work with the different methods of inheritance and we'll show you how to avoid using inheritance with Duck Typing. From there, we'll move on to some advanced patterns for object creation and you'll get a strong idea of how to use interesting patterns to present data to users and to bind data. We'll use the famous promises to work with asynchronous processes and will give you some tips on how to organize your code effectively. You'll find out how to create robust code using SOLID principles and finally, we'll show you how to clearly define the goals of your application architecture to get better, smarter, and more effective coding. This book is your one-way ticket to becoming a JavaScript Jedi who can be counted on to deliver flexible and maintainable code.
Table of Contents (18 chapters)
Mastering JavaScript Object-Oriented Programming
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface

Object prototypes


The flexibility of JavaScript objects is expressed primarily through the possibility of changing their structure even after their creation. Even while using a constructor to create an object, we continue to have this possibility. For example, you can write the following code:

var johnSmith = new Person("John", "Smith"); 
var marioRossi = new Person("Mario", "Rossi"); 
 
johnSmith.greets = function() { 
  console.log("Hello " + this.name + " " + this.surname + "!"); 
}; 

This code will create a new method greets() for the johnSmith object without affecting the structure of marioRossi.

Basically, while creating objects, we can start from a common structure defined by a constructor and then customize it to our needs.

But how do we change the structure of all objects created using a constructor? For example, suppose that after creating several object using the Person() constructor, we want all the Person instances to have the greets() method. We can do it by exploiting one of the most interesting features of Object-Oriented Programming in JavaScript—the prototype.

In our case, we will proceed in the following way:

Person.prototype.greets = function() { 
  console.log("Hello " + this.name + " " + this.surname + "!"); 
}; 

This assignment means that all objects created using the Person() constructor will instantly have available also the greets() method.

To be precise, the new method is not directly attached to each object, but it is accessible as if it were its method. This is possible, thanks to the prototyping mechanism that represents the basis of inheritance in Object-Oriented Programming in JavaScript, as we will discuss later in the book.

In JavaScript, the prototype of an object is a kind of reference to another object. The objects we create through the literal notation implicitly refer to Object as their prototype.

When we create an object using a constructor, its prototype object is the prototype of the constructor.

If we try to access a property or method of an object that the object itself has not, JavaScript looks for it among the properties and methods of its prototype. So, in our previous example, if we try to access the greets() method of the marioRossi object, JavaScript does not find it among its methods, but it will find it among the methods of its prototype.

The prototype of an object can in turn have another prototype. In this case, the search for a property or method goes up the prototype chain until you get object-the basic prototype of all objects.

JavaScript built-in objects have a prototype reference too. In most cases, their management is quite similar to the prototypes management of objects created through our constructors. This allows us to extend functionality not provided by the built-in objects in a rather simple and elegant way.

For example, if we want to make a padding method available to all strings, we can work on the prototype of the String() constructor, as shown here:

String.prototype.padLeft = function(width, char) { 
  var result = this; 
  char = char || " "; 
 
  if (this.length < width)  { 
    result = new Array(width - this.length + 1).join(char) + this; 
  } 
  return result; 
}; 

With this definition we can use padLeft() as if it were a built-in method of all strings, as shown in the following example:

console.log("abc".padLeft(10, "x"));      //"xxxxxxxabc"