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 literals


An object is a container of values combined to form a single data structure that has a particular identity. Normally, in fact, an object is used to represent a specific entity such as a person, an order, an invoice, a reservation, and so on, through an aggregation of data and functionalities.

The data is called properties and are represented by pairs of names and values. The functionalities are usually called methods and are represented by functions, even if they are nothing more than the same pairs of names and values as for properties, where values happen to be functions.

The simplest way to create an object in JavaScript is the literal representation, as shown in the following example:

var emptyObject = {}; 
var person = {"name": "John", "surname": "Smith"}; 

Through the literal notation, we represent an object by enclosing its properties and methods in braces. In the first statement, we created an empty object, an object without properties nor methods; all in all, not very useful but important to understand that an object is basically a list of pairs of values and, as with every list, it can be empty.

In the second declaration, in order to define the object person, we listed two pairs of strings separated by commas. Each pair consists of two strings separated by a colon. The first string is the name of the property while the second one represents its value.

Properties

To assign a name to the properties of an object, we don't have the same restrictions as for the JavaScript variable names. We can use any string, even if there is some constraint when accessing properties with particular names, as we are going to see.

The double or single quotes around the property name are generally optional, but they are required when the name does not follow the rules for variable names. So, we could write our definition of person as follows:

var person = {name: "John", surname: "Smith"}; 

But if we want a definition like the following, we are forced to use double or single quotes:

var person = {"first-name": "John", "second-name": "Smith"}; 

We can assign any value to an object property and any JavaScript expression, including another object. So, we can create nested objects as shown here:

var person = {name: "John", 
               surname: "Smith", 
               address: { 
                 street: "13 Duncannon Street", 
                 city: "London", 
                 country: "United Kingdom" 
               }}; 

As we can see, an object with its specific properties is assigned to the address property.

To access the values stored in an object property, we have two approaches. The first approach is the so-called dot-notation, by which we indicate an object and the property we're interested in, separated by a point:

var name = person.name; 

This is usually the most used approach because it is more compact and quite familiar to developers who have worked with other programming languages.

Using the second approach, we specify the properties of an object by indicating its name as a string in square brackets:

var name = person["name"]; 

This approach is mandatory when the property name does not follow the rules for JavaScript's variable names. For example, we cannot use the dot-notation to access a property named first-name.

If we try to access a non-existing property of an object, an error is not generated but returns the undefined value. In the following example, therefore, the age variable will get the undefined value:

var age = person.age; 

If we try to assign a value to a not yet defined property, we actually create this property initializing it with the assigned value:

person.age = 28; 

This example shows us the dynamic nature of JavaScript objects. The object's structure is very flexible and can be changed dynamically during the execution of a script. This feature gives us an alternative way for the creation of an object based on a kind of incremental definition. In practice, instead of completely defining a literal representation of our object, we can start from a basic representation and gradually enrich it with the properties we want. Following this approach, we can define our object person as follows:

var person = {}; 
person.name = "John"; 
person.surname = "Smith"; 
person.address = { 
                   street: "123 Duncannon Street", 
                   city: "London", 
                   country: "United Kingdom" 
                 }; 
person.age = 28; 

Besides being able to dynamically create the properties of an object, we can also destroy them at runtime using the delete statement. The following example shows how to remove the address property from our person object:

delete person.address; 

After the removal of the address property, any attempt to access it will return the value undefined.

Methods

While object properties represent data, methods represent actions that an object can perform. From a syntactical point of view, the definition of an object's method is quite similar to the definition of a property. Here's an example:

function showFullName() { 
  return "John Smith"; 
} 
 
person.fullName = showFullName; 

We can also assign a method to an object inside its literal representation as shown here:

var person = {name: "John", 
        surname: "Smith", 
        showFullName: function() { 
          return "John Smith"; 
        } 
}; 

ECMAScript 2015 allows us to define methods in literal notation in a more direct form, as in the following example:

var person = {name: "John", 
        surname: "Smith", 
        showFullName() { 
          return "John Smith"; 
        } 
}; 

Actually, the distinction between properties and methods is somewhat artificial in JavaScript. In fact, since the functions are also objects, a method is nothing more than a property that has been assigned a function.

Incidentally, since the value assigned to a property can change at runtime, it is possible that a property, which was initially assigned a function, can then be assigned a different value, such as a string or a number. Unlike other programming languages, a method is not a stable condition for a member of an object, it is not a characteristic of a specific property. We can simply affirm that a property is a method when it has a function assigned, but it is a dynamic condition.

In the previous example, we defined a function that simply returns a string and we assigned that function name to a new property of the person object. Note that we are not assigning the result of the function call to the property, but the function itself by means of its name.

The fullName property, since it has been assigned a function, is actually a method. To run it, we must refer to it by specifying parentheses as in a usual function call:

var nameAndSurname = person.fullName(); 

Of course, we can assign an anonymous function to a property directly as in the following example:

person.fullname = function () { 
  return "John Smith"; 
} 

The method that we just defined in the example is not so useful. It always displays the same string even if we assign a different value to name and surname of the person object. It would be useful to have a way to display the current value of the corresponding properties.

JavaScript allows us to reach this goal through the this keyword. The keyword represents the object when the method is invoked. So, we can rewrite our method in the following way:

person.fullName = function () { 
  return this.name + " " + this.surname; 
}; 

This guarantees the correct display of the current data at the time of the call.