Manipulating JavaScript Objects - Advanced JavaScript - JavaScript, 20 Lessons to Successful Web Development (2015)

JavaScript, 20 Lessons to Successful Web Development (2015)

PART II Advanced JavaScript

LESSON 13 Manipulating JavaScript Objects

image

To view the accompanying video for this lesson, please visit mhprofessional.com/nixonjavascript/.

JavaScript is an interesting language in that everything in it is an object. Arrays are objects, functions are objects, variables are objects, and so on, although they are objects of different types, or should I say class.

You see, by being structured this way, JavaScript is extremely easy to enhance by adding new classes (or types) of objects and then creating objects using these classes with the new keyword, as you’ve seen used for creating new arrays, for example.

You’ve also seen the prototype keyword used to allow a new function to be created to extend the JavaScript language by, for example, adding new functions to manipulate objects of the type Array. In this chapter I bring all these things (and more) together and show how you can create truly Object-Oriented Programs (OOP).

Declaring a Class

The first step in object-oriented programming is declaring a class, which defines a new type of object but doesn’t actually create the object. Classes group together a combination of data and the program code required to manipulate the data into a single object.

To declare a class you use the same syntax as for a function (because functions in JavaScript are actually objects), like this:

image

image

This code is known as a class constructor. It creates the new class UserClass and gives it two items of data it can hold: firstname and lastname.

It also sets up a method (another name for a function) that can be applied to the class called getName(), which returns a string with firstname and lastname concatenated together, separated with a space character.

image

See how the this keyword is used here to reference objects created using this class and the functions supplied to access the data in the object. You will also have noticed how an anonymous function is assigned to this.getName. This is a good use of an anonymous function, as it’s the only place the function is accessed. However, a name does get indirectly assigned to this function after all, because the function can be accessed through calling the getName() method on any objects created from the class.

Creating an Object

You can now create a new object (known as an instance) based on this class, as follows (in which the new object User is created):

User = new UserClass()

This creates the new object User, which has all the properties and methods defined in the class. The object doesn’t (yet) have any data in it, though.

By the way, in JavaScript, the terms method and function mean the same thing and are interchangeable. However, I choose to refer to a function by the name method only when it is provided as part of a class declaration, and is therefore a method that can be used on objects that are instances of the class. And I reserve the term function for stand-alone functions that are not part of OOP.

Accessing Objects

Once an instance of a class has been created using the new keyword, you can populate the object with data like this:

image

Or, alternatively, you can pre-populate the object (in the same manner as pre-populating a new array) when you create the instance of the class, like this:

User = new UserClass(′Julie′, ′Smith′)

Thereafter, you can read these properties back by accessing them in the following manner:

document.write(User.firstname)

And you can update object properties (in the case of this instance, for example) with a change of the user’s last name, like this:

User.lastname = ′Jones′

And you can call any of the methods provided by an object’s class, such as the getName() method of the UserClass class, like this:

document.write(User.getName())

Figure 13-1 shows the result of running the preceding code (available as class.htm in the companion archive) in a browser.

image

FIGURE 13-1 Calling the getName() method on the User object

The prototype Keyword

The prototype keyword can save you a lot of memory. For example, in the UserClass class, every instance will contain the two properties and the method. Therefore, if you have a thousand of these objects in memory, the method getName() will also be replicated a thousand times—this is highly wasteful.

However, because the method is identical in every case, you can specify that new objects should refer to a single instance of the method only instead of creating a copy of it. To do this, instead of using the following in a class constructor:

this.getName = function()

You can replace the statement with this:

UserClass.prototype.getName = function()

What is happening here is that instead of attaching the function to the this keyword (which would cause multiple instances of the function), the function is attached directly to the class UserClass via the prototype keyword.

All methods have a prototype property designed to hold properties and methods that are not to be replicated in objects created from the class. Instead, when the prototype keyword is used, the method (or property) is passed by reference so that there will only be one instance of the method (or property).

This passing by reference means you can add a prototype property or method to a class at any time and all objects (even those already created) will inherit it. For example, if you wish to create a standard message that will be used to create users logging into a website, you could extend the UserClass class with the following:

UserClass.prototype.Greeting = ′Welcome back ′

This type of method or property (created using the prototype keyword) is known as static. A static method or property has a single instance that is accessible from any object created from a class.

You can display this single instance of the property at any time from any object created from the class, like this:

document.write(User.Greeting)

You could then expand the getName() method to supply the greeting, like this:

image

Now, when getName() is called on the object, it will display the following (pulling the Greeting string from the prototype of the class so that only a single instance of the string exists, no matter how many instances of the object there are):

Welcome back Julie Smith

Extending JavaScript Functions

In Lesson 12 I briefly glossed over the prototype keyword when showing you how to attach a new function (now called a method, because we’re discussing OOP) to objects of the type Array. Now that you have read this far, you should understand exactly what was going on.

In the replacement Join() method, the Array class has its prototype property updated by adding to it a new method called Join().

I have updated the example, shown next, by assigning the method directly to Array.prototype.Join (rather than first creating the method, giving it a name, and then assigning that name to Array.prototype.Join, as was previously the case):

image

You should now see how this code simply adds a new static method to the Array class so that it can be called on any object of that type, like this:

MyArray.Join()

You can extend any of JavaScript’s classes in a similar manner, even to the point of rewriting it to work the way you prefer, as is the case with frameworks such as jQuery (see jquery.com), which extensively extends JavaScript to provide a wide range of additional functionality.

For example, if you wanted to make the StrRepeat() function from Lesson 12 operate as a method on String objects, you could use the following code to add a method called Repeat():

image

Then, for example, to display the string ′Hip, Hip, Hooray. ′ three times, you can use the following statement (shown in Figure 13-2):

document.write(′Hip, Hip, Hooray. ′.Repeat(3))

image

FIGURE 13-2 Implementing a new Repeat() method

image

In the preceding example, rather than attaching to a string variable, the repeat() method is attached directly to a string. To JavaScript, this is the same thing because such a string is an object of type String.

Summary

You are now becoming a power JavaScript programmer, capable of bending the will of the language itself to your desire. All that remains to finish your training (before moving on to using JavaScript in meaningful ways in your web pages) is to enhance your knowledge a bit by looking at things such as how to gracefully handle errors in your code and how to use regular expressions for powerful pattern matching—both of which are in the following lesson.

Self-Test Questions

Using these questions, test how much you have learned in this lesson. If you don’t know an answer, go back and reread the relevant section until your knowledge is complete. You can find the answers in Appendix A.

1. What syntax do you use to declare a class?

2. How do you create a new instance of a class?

3. In a class declaration, how do you declare properties?

4. In a class declaration, how do you declare methods?

5. How can you access a property of an object created from a class?

6. How can you access a method of an object created from a class?

7. What is the purpose of the prototype keyword?

8. What is a static property or method?

9. How do you apply the prototype keyword?

10. How can you extend JavaScript by adding new functions?