You need constructors for class objects, and this article discusses constructors and inheritance within JavaScript. If you're familiar with object-oriented programming, this section will be easy to pick up. If you're new to object-oriented programming, some of these concepts are difficult to understand at first. However, constructors are important part of class objects, and inheritance saves you time when designing your applications.
Building a Class Object
Instantiation is done through class object constructors. Constructors can be public or private and they can take parameters or be parameterless.
var Customer = function (first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
};
Customer.prototype.Edit = function (first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
};
We covered the "Edit" method in the previous chapter, but this chapter focuses on the constructor that allows you to instantiate the Customer object. Incidentally, you don't need to instantiate static classes and their methods, but JavaScript works differently than standard object-oriented languages. Objects can be thought of as functions, and these functions can be called from anywhere in your code.
Remember that we instantiated the Customer object by assigning it a variable in our main script. The following code creates the Customer object and assigns the object to the "myCustomer" variable.
var myCustomer = new Customer('Joe', 'Smith');
In this example, the function takes two parameters: first_name and last_name. The parameters are used when instantiating the object, but you don't always need to use parameters when creating objects. For instance, the following code will also define a Customer object.
var Customer = function ( ) {
};
Customer.prototype.Edit = function (first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
};
Now, when you want to instantiate the object, you only need to use the main constructor without any parameters. The following code instantiates the same object but notice the difference.
var myCustomer = new Customer( );
With instantiation of the Customer object, you can now invoke the method. The following code invokes the "Edit" method within the class object.
myCustomer.Edit('Joe', 'Smith');
Notice that you don't use "Customer" when invoking the method. You use the variable that holds the class object to invoke the method. This is an important part of object-oriented programming. You can create several object variables that instantiate the Customer object and then call the Edit method. The container will only affect the variable used instead of globally changing information in one place. For instance, the following code uses two variables for a Customer object, but each variable has its own information since it is its own container for each variable.
var myCustomer = new Customer( );
var myCustomer2 = new Customer();
myCustomer.Edit('Jane', 'Smith');
myCustomer2.Edit ('Joe', 'Smith');
Notice we've instantiated two objects and edited the first and last name twice. Each variable is its own container, so myCustomer contains "Jane Smith" and myCustomer2 contains "Joe Smith."
Objects and their associated containers enhance your code because you can contain multiple objects and use them separately instead of editing the same content across the same object.
JavaScript and Inheritance
JavaScript isn't a standard object-oriented language. The language uses a prototype chain to filter down variables and their values. JavaScript is more linear than standard inherited languages such as C++, Java or C#.
Let's use the same Customer object except let's change some of the object code.
var Customer = function ( ) {
active: true;
IsActive: function ( ) {
return active;
};
};
The above code changes the logic of our Customer object. Instead of setting up a first and last name for the customer, we've created an "IsActive" method that returns if the customer is active. When you instantiate the Customer object in your code, the "active" property defaults to the value of "true." When you call the "IsActive" method, you return the "true" value from inheritance.
Take a look at the following code.
var myCustomer = Object.create(Customer);
myCustomer.active = false;
document.write( myCustomer.IsActive() );
The above code first creates a Customer object and then assigns the object to the myCustomer variable. When you instantiate the object, the "active" property is automatically set to "true." However, inheritance and object-orientation lets you change the properties of your code to different values. In the above code, the "active" property is changed to "false." After the property change, the "active" property is printed to the screen using the "IsActive" method. Because the JavaScript language inheritance the properties from the main object and the myCustomer variable contains the current state of the object, "false" is printed to the screen instead of the default value of "true."
When you create your objects, you need to also define properties. With standard object-oriented programming, when you attempt to call a property that isn't defined, an error is returned. With languages such as Java or C++, you can't compile the program when you call non-existent properties. However, with JavaScript, you can "accidentally" call a property and no error is returned. Instead, the "undefined" value is given to a property that isn't defined.
Let's take the Customer object again. We have an "active" property defined, but we no longer have the "first_name" property defined. What happens when we attempt to print this property? Instead of throwing an error, JavaScript returns undefined. The following code is an example of this JavaScript syntax.
//printing the first_name property
var myCustomer = Object.create(Customer);
myCustomer.active = false;
document.write( myCustomer.first_name );
//the Customer object
var Customer = function ( ) {
active: true;
IsActive: function ( ) {
return active;
};
};
We've added some comments to the above code to make it easier to read. The second part of the code is the Customer object. The code is the same as the previous example with an active property and an "IsActive" method that returns the active state of the customer. The first part of the code attempts to print the "first_name" property, but of course it's not defined in the object. The returned value is "undefined" until you define it in your code. Be careful with this type of code. Undefined variables can change logic in your control flow, so it's standard to always define properties and objects when you create functions. Remember, JavaScript objects are functions unlike standard object-oriented classes in other languages.
You can also create objects that inherit from previously created objects. For instance, we have the Customer object, but suppose we want to customize an additional object that inherits from the previously instantiated object. Using the above Customer object, here is an example of an inherited object.
//first, instantiate the Customer object
var myCustomer = Object.create(Customer);
myCustomer.active = false;
//now instantiate another customer that inherits from the previous one
var myNewCustomer = Object.create(myCustomer);
document.write (myNewCustomer.active);
//the Customer object
var Customer = function ( ) {
active: true;
IsActive: function ( ) {
return active;
};
};
Again, we've commented the JavaScript code to make it easier to read. The first part of the code instantiates the Customer object. The second part of the code also instantiates the object, but instead of creating a new container with a new instance, the "myNewCustomer" object is instantiated with inherited information from the previous instance. When the document.write function is called, the new myNewCustomer object prints "false" for the active property. This is how the JavaScript language inherits properties.
Pattern Matching with Regular Expressions
At some point in your JavaScript programming career, you'll need to search strings for values and perform an action based on finding a pattern. You can write your own functions to search strings or you can use premade logic called regular expressions. Regular expressions are more complex JavaScript functionality, but it saves you hours of time writing your own string search function and debugging it. Regular expressions are used in most standard languages with a few minor differences in language syntax. This lesson describes regular expressions and how you can use them with your JavaScript string variables.
Creating Regular Expressions
There are two ways to create the pattern you want to find. First, you can create a regular expression variable with your associated pattern. For instance, the following code creates a regular expression string variable that finds the name "Joe" in a string. The "/i" modifier tells the regular expression engine that the search should be case insensitive, which means "joe," "jOe," and "Joe" would all be a match.
var pattern = /joe/i;
You can also use the RegExp object as defined in the JavaScript language reference. The following code is an example of using the class object instead of the basic regular expression string.
var pattern = new RegExp("/joe/i");
Notice the above code uses the "new" keyword and passes the expression to the object constructor like we learned in the previous lesson.
There are a number of rules and expression characters you use to search strings. The above example uses a modifier, which is indicated by the forward slash. You can also use "g" as a modifier, which indicates that you want to perform a global search instead of stopping the search after the first instance is found.
Let's create some other examples of regular expressions. Brackets are used to find a range of characters. For instance, the following regular expression creates a range of characters.
var pattern = new RegExp("[im]/i");
In this example, we use the JavaScript object to create a list of characters to search. The brackets indicate to the regular expression engine to search for the letter i or'm within a string. If you had a string with the value "Im the JavaScript guru," the expression would match "Im" and "i" within the JavaScript phrase. Notice that the "Im" phrase is capitalized but yet matches even with the bracketed expression set with a lower case "i." This is because of the "/i" modifier that tells the engine to do a case insensitive search.
You can also set a range instead of defining a specific set of characters. For instance, suppose you want to return a pattern match when you find the characters A through F in a string. The following code returns a match if the range is found in a string.
var pattern = new RegExp("[A-F]/i");
Again, the case is insensitive and the dash or hyphen indicates to the engine that you want to find a range between the two character values. In other words, if you have the string "I know how to code JavaScript" as a string, the pattern would match the "a," "e," and "c" characters in the string.
You can also use the opposite logic to search a string. Suppose you want to find all instances in a string that did not have the letters A-F. Let's use the same phrase and RegExp expression except let's reverse the logic. Look at the following code.
var pattern = new RegExp("[^A-F]/i");
The carrot character ( ^ ) is the logical reverse that means "NOT" in your regular expressions. The above expression says return a value if it is NOT in the range of characters. Let's use the same string value "I know how to code JavaScript" as the searched phrase. In this example, all characters except the "a," "e," and the "c" characters are returned. Incidentally, the same rules for bracketed characters apply to numbers. You can search specific numbers or a range of numbers, and then you can reverse the logic and find instances of a number that are NOT found in a value using the carrot character.
Regular expressions can get long and complex.
Using Your Regular Expression Patterns
We've looked at how you can create your search patterns, but how do you use them? The next step is to execute your regular expressions and return a match if the JavaScript engine finds one. JavaScript uses the "exec()" method defined in the RegExp object to execute your pattern and return matches. If no pattern is found, then the return value is null.
Let's use the same pattern as we used previously. We'll use the ranged character search for the same phrase we mentioned in the beginning of the lesson. Here is the JavaScript code.
var pattern = new RegExp("[A-F]/i");
var stringsearched = "I know how to code JavaScript";
var result = pattern.exec(stringsearched);
// the result returns "c"
The first character found in the regular expression pattern is "c" in the stringsearched variable. The regular expression isn't set to global, so the first match is returned.
Using the reverse NOT logic, you can change the search pattern. The following code uses the NOT operator in the regular expression engine.
var pattern = new RegExp("[^A-F]/i");
var stringsearched = "I know how to code JavaScript";
var result = pattern.exec(stringsearched);
// the result returns "I"
This code returns the first instance where a character is NOT in the defined range. In this case, the first character is not within the range, so the letter "I" is returned. If no match is found, a null value is returned. The following code returns null.
var pattern = new RegExp("[Y-Z]/i");
var stringsearched = "I know how to code JavaScript";
var result = pattern.exec(stringsearched);
// no letters matching the range are found, so null is returned.
Using String Methods Search and Replace
JavaScript gives you several ways to perform an action, and regular expressions have an alternative to the RegExp object. You can also use the string object's search and replace methods. The search method is similar to the exec RegExp method. The replace method replaces the first match with an alternative string.
First, let's take a look at the search function. The following code uses the same logic as the previous example but replaces the RegExp object with the string object and search method.
var stringsearched = "I know how to code JavaScript";
var result = stringsearched.search([A-F]/i);
The same string phrase is used and the same regular expression search pattern is used. The same results are displayed except this logic uses a different method.
Suppose you want to search a string for a pattern and replace it with another string. This type of functionality is common with JavaScript code within large applications. Look at the following code as an example.
var stringsearched = "I know how to code JavaScript";
var result = stringsearched.replace([B-D]/g/i, "A");
In the above example, the string method "replace" is used to replace all characters that match B, C, or D with the character "A." The following code prints the result to the screen.
document.write(result);
//the phrase "I know how to AoAe JavaSAript" prints to the screen
Notice the replacement character is capitalized even if the match is not capitalized. That's because the characters set in the replacement string keep their case while the "i" in the regular expression tells the search engine to find any value regardless of case.
You can also use the "replace" and "search" phrases without regular expressions. However, you have fewer options with a simple string search. For instance, there is no case insensitive search with a standard string search without regular expressions. The following code is an example of a search function without regular expressions.
var stringsearched = "I know how to code JavaScript";
var result = stringsearched.replace("Java", "C");
document.write(result);
The above result phrase contains "I know how to code CScript" when printed to the screen. Notice the capitalized letter in the search parameter. This is required when working with simple search phrases since the letters "J" and "j" are different binary values in computer languages.